Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I have a little state machine in Java which has an unusual state.
The issue is ABORT ...
The task can have two final states: SUCCESSFUL, and FAILED.
But it would be nice to sometimes ABORT a task while it's in the queue, before it ever gets executed and during execution.
While ABORTED is a final state I don't want to have two (or even N) failed states.
FAILED and ABORTED will then have to be checked for. I could also see other failed states like TIMEOUT.
I guess I could have a generic CAUSE for the failure... which could be a TimeoutException, AbortedException, if I want to check for why it failed. Then I could just look at the cause.
Still not super happy with that either.
Any thoughts?
Understanding your problem only abstractly, here are my thoughts on this state machine.
I think FAILED needs to be a category comprising causes such as ABORTED, TIMEOUT, SEGFAULT, UNKNOWN etc. I don't like FAILED as it seems indicates there was some defect in the program or the environment, but I cannot think of a better antonym for SUCCESSFUL that doesn't convey the same meaning.
If the Java framework specifics are your concern, you could easily have an enum that represents these states without much trouble. You would only be checking for SUCCESSFUL or !SUCCESSFUL, as all non-successful things probably deserve similar handling at some level.
While you could take the Exception route, I do not find it sensible to have an AbortedException, especially if that is not actually an exceptional circumstance. Code that is expected should not trigger exceptions, when possible.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 days ago.
The community is reviewing whether to reopen this question as of 6 days ago.
Improve this question
Python docs for asyncio.create_task state:
Important: Save a reference to the result of this function, to avoid a task disappearing mid-execution. The event loop only keeps weak references to tasks. A task that isn’t referenced elsewhere may get garbage collected at any time, even before it’s done. For reliable “fire-and-forget” background tasks, gather them in a collection:
What's the benefit for asyncio to use a weakref instead of a strong reference to the created task until it is completed? As the warning above suggests, there's definitely at least one benefit to keep strong refs -- which means there's likely an offsetting benefit for weakrefs. Note that with strong refs, asyncio could, upon completion, either remove the reference entirely or switch to weakref, depending on what is required by the asyncio logic.
The use case implicit in the documentation warning is: we don't want to wait for the task (in particular, the task's return value is not used), but we do want to give the task a chance to run eventually.
Note that asyncio.TaskGroup context does keep strong references to the tasks it creates. However, it's not suitable for the above use case, since upon exit, the context blocks (it waits for all the tasks' completion). (Also, it keeps a strong reference to the task even after it completes, so it will cause memory leaks if the context lives much longer than the tasks.)
Sorry if not really an answer to the "why" - I think just whoever actually implemented it can come up with the real motivation - if there is any besides what you quote in the question.
On a second though, one can't even check if a weakrefered object has any hard-references until it is about to be switched into and executed: at task-creation, the only hard reference to it is returned to the caller.
So, once the decision was taken not to hold hard-references to tasks due to fear of resource-leakage, the "bomb" was out. And it was likely only perceived later, but them making it hold a hard reference would probably change too much of the working behavior for certain workloads.
update As a drawback to holding a hard-reference: if the tasks are created like "fire and forget", eventually done tasks would carry their result (or exception) data, and could not simply be "dropped": they'd need to be kept indefinitely, and that could be a major resource leak for a server-type app. On the other hand, were to "draw the line" that a complete task should be considered "orphan" and could be discarded? So, it appears the "line" chosen by the implementation, even if not that well though, is the task having a hard reference elsewhere.
In the source code, when a task is created, it is immediately registered as ready in an internal running loop structure - that is a hard reference - when the loop cycles through on iteration and fails to call any task there, this hard reference is dropped. That this "dropping" is not deterministic maybe is a bug that could be fixed.
/update
Maybe now the problem is getting some awareness, beyond this notice, (I've seem a twitter thread about it last week as well, with high-profile Python folks worried about the behavior), they take the step for an incompatible change there - or come up with a create_task sucessor that does the right thing. TaskGroups, as you put it, are not quite it - they are more substitutes for asyncio.gather - and even there with some drawbacks (the whole group is cancelled at __exit__ if a single task throws an exception, with no practical workaround)
For anecdote, I experimented around, and the results are really nasty with random task-drops starting at around 2500 concurrent tasks with this code:
import asyncio, random
async def blah(n):
await asyncio.sleep(random.random())
results.add(n)
async def main(m):
for i in range(m):
asyncio.create_task(blah(i))
await asyncio.sleep(1.01)
def doit(m):
global results
results = set()
asyncio.run(main(m))
try:
assert list(range(m)) == list(results)
except AssertionError:
print(f"For {m} tasks, missing {m - len(results)} results: {set(range(m)) - results}")
Including an await asyncio.sleep(0) in the loop where the tasks are created makes it all run flawlessly up to millions of tasks.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
in go programing, we always create a go routine like
go func(){}
i want to know whether keyword "go" is an atomic operation, what if create a go routine fail by this operation.
can i monitor a new go routine created success or not?
Or maybe this keyword "go" create a routine that will never fail.
The spec says nothing about failure to create the goroutine or invoke the function, so behavior at this point is up to the implementation and there is no defined way to determine success or failure.
The kinds of errors you would encounter on goroutine creation will be fatal errors (likely due to resource exhaustion), not something that can be caught and handled gracefully. This is similar to the kinds of errors you would encounter on invoking a function.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
In clojure concurrency, I would like the thread that I spawn kill itself if it take to long to do it's task, similar to what Golang ctx withtimeout provide. how should i do it?
Mind you I dont have any knowledge of java thread.
You can't kill a Java thread cleanly, so people usually write very long-running threads to check a flag occasionally, and keep working only if appropriate.
On the other hand, a thread's client can stop waiting for an answer. If you start the thread with future, you can use the timeout parameter on deref at https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/deref, or check on it with future-done?.
When you have a lot of async stuff going on, the better Go-like algebra in Clojure's core.async library can be helpful (https://clojure.github.io/core.async/) as an alternative to raw Java threads.
never mind, apparently there is something called future and promise..
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Please take a look at my recent question here: Deadlock with no user code
How can you tell when the debugger is lying to you in this way? Other than, of course, showing that what it is telling you is impossible?
I don't like relying on that since I've seen so many 'impossible' states in a program that were in fact happening due to some subtle or esoteric problem.
Yes, those are pretty wacky stack traces, particularly the 1st one. Hard to theorize how that happened. It doesn't usually get that screwed up unless you debug optimized code.
Which is hint #1, never trust what the debugger tells you when you have to debug release built code. Strongly avoid it, you don't always have the luxury when you need to troubleshoot a deadlock however.
Strong hint #2 is paying attention to the code-flow. The normal one for a blocked thread, bottom to top in the Call Stack window, is yourcode => runtime (msvr120) => winapi layer (kernel32 et al) => native api (ntdll.dll). This is generally the case, there are a few cases where this flow is reversed, callbacks from the OS into your code, like window notification, thread-start (always at the far bottom of the stack for example), I/O completion.
Which is what's wacky, there is no realistic scenario where a low-level native api function like ZwWaitForSingleObject() could ever directly call into the C runtime library. That's bogus, only the top entry (Block) could be accurate. Yes, tough debugging that way.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
Let's say I have published this project containing a function:
int sum(int a, int b) {
return a + b;
}
I have written the tests:
assert(1==1);
assert(2==2);
All the tests pass and so I claim that my project is 100% good and tests have 100% coverage.
My client is smart and knows about fault injection. So he injects a fault in my project and makes it:
int sum(int a, int b) {
return -1;
}
My tests still pass and so he says my tests are useless. Great.
But is there any other use of software fault injection?
I read that it is used to assert robustness of a software? How? Can you use this example and show that is possible?
Also, I was reading some papers that showed how faults can be injected in SOAP messages passed around in the web (*basically meaning that messages that were being sent from one machine to another in the web were injected with faults and the results were observed)*. How is this going to be useful? Obviously this will go wrong and what can you conclude from it?
Please quote with simple examples.
With regard to injecting faults into SOAP messages (or other data sent over the wire): that could be viewed as a form of "stress testing", to determine how robust your application is in the face of network problems, data corruption, malicious clients, and so on.
As you said, "obviously this will go wrong". But the purpose of stress testing isn't to see if your application works as intended (under normal conditions). When you feed the application garbage data/massive volumes of data, deliberately corrupt config files, or suddenly disconnect hardware which is being used, etc., it's expected that your program will not "work". But you want to make sure it will not do something bad like crashing, destroying valuable data, revealing confidential data to unauthorized persons, and so on. If it is an application which services multiple users at the same time, you also want to make sure that illegal input from one user cannot result in a loss of service to other users.
If you have never stress tested your application, the results will probably surprise you!