-
Notifications
You must be signed in to change notification settings - Fork 177
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
Dont catch ocaml runtime exceptions #964
Conversation
7755e44
to
a19f764
Compare
I'm in favour of this change. |
When the unipi unikernel runs out of memory while fetching its data, the out of memory exception is handled and somehow turned into an empty result (the unikernel finally crashes because of that). |
a19f764
to
e914f3b
Compare
I added a couple of commits. One avoids catching OOM/SO in The other commit avoids catching OOM/SO in I'm not entirely sure about this second change. It might be reasonable for someone to call (Also I rebased on master.) |
I'm concerned that these exceptions can put Lwt in an inconsistent state. You mention the main loop, but the change in Also, this means that it is not longer possible to contain these exceptions to a particular thread. Instead, they might be caught at some completely unrelated place. If we want these exceptions to stop the program, maybe we should call |
The change with I guess inconsistent
The aim is to make it only possible to catch outside of Lwt. Specifically, outside of the In addition, it is correct that it is no longer possible to catch these exceptions using the tools provided by Lwt. However, it is possible to catch them from within a non-Lwt section of the code. E.g.,
Basically, these exceptions can be handled at the very local scale (sub-promise scale) or very globally (above
One issue with calling Maybe we could register a global handler for these exceptions and make it an option so that it can be set to be ignored. I'm not a big fan of registering global handlers through mutable state. But if it is important for some application to be able to handle runtime exceptions maybe it is worth adding that feature. Is there a way that Should we had a flag to capture/not the exceptions? Should we add a global mutable ocaml-runtime-exception handler? |
As a general rule, you want to propagate the exception to let the user program do some clean-up; and as a general rule also the programmer should only definitely catch the exception if they know that no broken state escapes. Typically, they let the program terminate. Without looking at the details of the implementation, the change sounds good in principle (modulo the caveats from my reply on discuss). |
Does it make any difference if the out of memory exception is not ignored by the error handler (https://github.com/roburio/unipi/blob/fbaaa27cd641ab17b1f840ece441f8bdacf60b2e/unikernel.ml#L184)? let ignore_error _ ?request:_ _ _ = () |
Suppose you have this piece of code: let x = Lwt_main.run (Cohttp_lwt_unix.Client.get ...) What I mean is that let rec background_thread () = let%lwt () = ... in background_thread ()
let () = Lwt.async background_thread So, indeed, you can catch the exception outside At the moment, you have a lot more control. The default behavior of Lwt is to stop the program if there is a stack overflow (or any uncaught exception) in the background thread. You can make the thread more robust by catching exceptions locally. You can use For a more concrete example, do you see how to update Cohttp so that a Web server can continue running without leaking file descriptors when the request handler fails with a stack overflow? Or do you consider that the Web server should just stop when this happens?
OCaml already calls |
I am less familiar with Lwt but with fibers in multicore, every fiber would need to be discontinued in reaction to this exception, causing each fiber to be restarted with an exception, and subsequently I am on the fence regarding the treatment of |
I wouldn't recommend writing this code. Doing so you may give the impression that the background thread is executing concurrently and somewhat independently from the Essentially, in that code, there is a hidden bit of control-flow where the call to In that sense the exception happens in the context of the Still, I understand that some patterns of code similar to this one may need to have a more fine-grained error-management mechanism. Especially re: So I'm thinking of ways to allow more flexibility for users that might need to catch those exceptions specifically, and may need to resume work and/or clean-up resources. I'll push some more commits to try to accommodate those needs. |
@Julow wrote
@vouillon replied
This is a great observation, thanks, and indeed fixed in robur-coop/unipi@1d2f5e0. But, this is the |
Thinking about this a bit more, we could do the following as an intermediate solution: Later on, we can decide whether to change the default. We can make this decision based on feedback and actual uses. |
e914f3b
to
2f1edec
Compare
looks fine, but I've not much knowledge about the code and internals:
But under the line, I understand that this is a good compromise, and for me it is better than the earlier behaviour (I'll initialize Lwt to not catch the OOM and SO exceptions -- I also don't use the Lwt.*value functions). |
I also dislike the names I picked in this commit. I need to think about it a bit more to find something good. In the meantime suggestions are welcome. Regarding performance regression, I think that it shouldn't affect performance of code that does not raise exceptions. That is because the diff for this PR is essentially replacing Re |
@vouillon What do you think about the approach taken by this PR? |
64dc203
to
f064ff1
Compare
Dear Raphael, thanks for your work. I appreciate the revised API (although it introduces mutable state). |
This looks good to me, except for the small comment I made. |
Out-of-memory Stack-overflow
aa72d56
to
032b120
Compare
Exceptions such as Out-of-memory and Stack-overflow shouldn't be caught by Lwt.