New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
link/unlink is exception unsafe #286
Comments
That last paragraph sounds like the most pragmatic approach to me? |
I'm not sure what exactly the problem is here. Until |
Yes it is, the link exception could interrupt the important clean up in:
hm, though probably we could argue that Another bad example:
The link exception could arrive after |
There is no need to bracketize And aplications shouldn't make any assumptions about what order async exceptions will be delivered in, because CH provides no such guarantees. |
Since that's the case, can we close this issue? Should I add something about this to the documentation? It feels to me like I should probably compile the various issues and conversations around async exceptions in Cloud Haskell - and there have been many - into a page, and publish it to the website. Or would it be better placed in the haddocks? |
I'm not getting why there is no point in calling unlink if the original exception is caught and handled. Or if I did get it in the past, I've forgotten how :) +1 for discussing async exceptions in the documentation. |
Yes actually that's a good question... I think the answer is in the client's court. Calling unlink means I no logger want link exceptions. If I want to avoid having some other arbitrary async exception interfere with unlink, I can mask it. One might argue that you should always mask unlink, but that's another matter entirely. Now assuming you mask unlink and miss the link exception, who cares? You were done with linking anyway. The more onerous issue is that you might've missed another async exception that mattered to you more than the link exception. The broader design issue here, and we should document this when we update the docs around async exception behaviour in general, is don't use links if you require time to do cleanup. Instead you should use monitors, and kill your process in response to a monitor notification if that's the semantics you require. Better still, use supervisors, and encode the dependency between running processes that way. If all those processes are managed processes based on the client-server library, they'll each get a chance to do cleanup in a structured fashion, and can even deal with their inbox without risking message loss by using the So I guess my perspective is, these issues are probably best solved higher up the value chain in libraries, rather than having complex semantics surrounding the primitives those libraries depend on. Not many erlang programmers use messaging primitives directly all that often. 95% of production erlang code uses gen_servers and supervisors, which have well understood models for fault tolerance, built on the underlying semantics. |
I agree that the semantics shouldn't be complex. The primitives in the foundations should be simple to use. But, alas, I'm fine promoting this task to discussing the problem in the documentation. |
Looking at the code, I'm not sure some of your assertions hold @facundominguez. After sending a control message to the node controller, |
And in actual fact, |
Suppose I have the following code
If
f
is interrupted with an exception,unlink
might never be called. Thus I rewrite to:But this still doesn't help, because
unlink
is interruptible, thus ifunlink
is interrupted with an exception, the process will remain linked topid
after leavingf
.How about
?
This introduces the potential for blocking indefinitely. If
pid
dies whileunlink
is executing, the link exception cannot be thrown becauseuninterruptibleMask_
is in effect. However, whenunlink
completes, the exception cannot be thrown either, because the veryunlink
definition does not allow it. The only way to avoid illegal behavior would be to have unlink never return or somehow don't throw the link exception (the latter looks impossible to me).The second attempt is the one I would expect to work. The problem is determining what tweak of
unlink
semantics would make it to work.I would like
unlink
to be uninterruptible, but I don't see how that could be implemented. An alternative is to guarantee that whenunlink
runs with exceptions masked, it always unlinks before returning, but it might return with an exception if it is interrupted during its execution.The text was updated successfully, but these errors were encountered: