-
Notifications
You must be signed in to change notification settings - Fork 176
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
cohttp server crash when client dies mid-transfer #511
Comments
Also, if I wrap
instead of the expected:
module Server = Cohttp_lwt_unix.Server
let callback _conn _req body =
let%lwt body = Cohttp_lwt_body.to_string body in
Server.respond_string ~status:`OK ~body ()
let server port =
Server.create ~mode:(`TCP (`Port port)) (Server.make ~callback ())
let () =
Lwt_engine.set (new Lwt_engine.libev);
try
Lwt_main.run (server (int_of_string Sys.argv.(1)))
with
| Unix.Unix_error (_, _, _) -> prerr_endline "Exceptional!" |
And I should have checked, but |
Backtrace from
The
|
So it looks like the crash is coming from Lwt's async exception hook. If I set: Lwt.async_exception_hook := ignore before the call to |
I've just got the same error. Having a non catchable exception is indeed a bit strange and I had no idea what happened... Thanks for the fix/workaround :-) |
Something changed either in lwt and or cohttp which triggers this. See mirage/ocaml-cohttp#511 for the workaround, which seems to be working fine (at least the tests now pass).
@samoht You're quite welcome, I'm glad it's useful! There are still errors, particularly when larger bodies are submitted. But it doesn't crash the server and does not (seem to) leak resources. A possibly more helpful, definitely more verbose async exception handler that I've been using since writing this: Lwt.async_exception_hook := (function
| Unix.Unix_error (error, func, arg) ->
Logs.warn (fun m ->
m "Client connection error %s: %s(%S)"
(Unix.error_message error) func arg
)
| exn -> Logs.err (fun m -> m "Unhandled exception: %a" Fmt.exn exn)
); |
I suspect the culprit is here, in Cohttp handles exceptions from the user's callback function, but not errors writing the response after the user callback returns successfully: |
Please correct me if I'm wrong:
|
I'm not sure what a user-supplied connection error handler would do. The client of a web-server is always free to close the connection at any point, so this really isn't an error. I think the real problem here is that cohttp's The server loop would handle errors from |
Also, conduit's error handling is a little unusual. Instead of using
Since this swallows all errors, it then wraps
This makes tracing it a bit harder than necessary, because Lwt doesn't report the callback handler as an async thread. It also suppresses errors from e.g. |
@talex5 I have a small, local patch to conduit that I made while trying to track this issue down. All it does is wrap the |
I can't speak for the cohttp maintainers, but I think it would be good to clean things up here. Probably the whole of the new-connection-handling code should run in
|
This sounds sensible to me. That code was written a very long time ago, and our understanding of Lwt error handling idioms has moved on since then... |
In my experience, in those languages, users will set 2 handlers: on I'm not saying this is the way to go, I'm presenting it as an alternative. If there's no |
I came across this bug in a fun way: simply running |
came across this as well, any update on a more permanent fix than ignoring all exceptions? |
The permanent fix is for someone to contribute a PR that modernises the interface as @talex5 suggests above: #511 (comment) Contributions welcome to that effect! |
For a quick fix, we could just change the default exception handler to one that logs. Cohttp already catches exceptions from the user callback separately, so anything that gets here is going to be an error writing the response. We could log However, that only fixes the Unix backend. To fix e.g. Mirage too, it might be better to change the
|
The following server will crash (usually) if the
wrk
process is canceled with actrl-c
. I've seen at leastEPIPE
,ECONNRESET
,EPROTOTYPE
errors while testing this.This may be related to #503
Using OCaml 4.02.3, cohttp 0.21.0. Tested on 64bit OSX and Linux with
libev
/conf-libev
installed.Server code:
Client using
wrk
:The
put.lua
script creates a blob of bytes to send as aPUT
request to the server.put.lua
:The text was updated successfully, but these errors were encountered: