-
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-eio: "handle used after calling close" while reading body / Closing connection too soon? #965
Comments
Confirming that this ugly “Lazy.force” hack avoids the problem (but preserves the API :) ): diff --git a/vendor/cohttp/cohttp-eio/src/client.ml b/vendor/cohttp/cohttp-eio/src/client.ml
index a9942f1e..fce2feaf 100644
--- a/vendor/cohttp/cohttp-eio/src/client.ml
+++ b/vendor/cohttp/cohttp-eio/src/client.ml
@@ -107,7 +107,7 @@ let call ?(pipeline_requests = false) ?meth ?version
Eio.Buf_read.of_flow ~initial_size ~max_size:max_int conn
in
let response = response reader in
- (response, reader))
+ (response, Buf_read.take_all reader |> Buf_read.of_string))
in
match conn with
| None -> |
Ping @bikallem |
/cc @talex5 @haesbaert It seems to be related to eio luv backend. Any ideas? @smondet Can you replicate this in eio linux (uring) backend too? |
It's because the Looks like this broke it: #958 |
However, we should make Eio not crash the event loop in this case! |
One way to fix this would be to take a body parser argument and return the result of that, rather than leaving the connection open after the call returns. |
Do you mean like read the whole body like @smondet suggests? |
@bikallem I think he means something more parametric like passing a function to handle the Maybe like this? val Cohttp_eio.Client.call : ?pipeline_requests:bool ->
?meth:Http.Method.t ->
?version:Http.Version.t ->
?headers:Http.Header.t ->
?body:Cohttp_eio.Body.t ->
?conn:#Eio.Flow.two_way ->
?port:int ->
?on_body: (Eio.Buf_read.t -> 'a)
< net : Eio.Net.t; .. > ->
host:string -> string -> Http.Response.t * 'a
Or even val Cohttp_eio.Client.with_call:
?pipeline_requests:bool ->
?meth:Http.Method.t ->
?version:Http.Version.t ->
?headers:Http.Header.t ->
?body:Cohttp_eio.Body.t ->
?conn:#Eio.Flow.two_way ->
?port:int ->
< net : Eio.Net.t; .. > ->
host:string -> string ->
((Http.Response.t * Eio.Buf_read.t) -> 'a) ->
'a because you may want to do something different with the body depending on the response? |
Ah, okay. Yes, this should probably solve the connection being alive issue. |
The problem seems to be that we have one function (
I suggest reverting the changes to |
Just to give an update. I am working on a fix for this issue along with a few others. |
I agree with your suggestion. Thanks for the update |
This http-client code works when the content-length is “small” but starts
failing hard once it is a few kilobytes:
The exception cannot be caught (it seems to be in the loop of the Luv backend):
Looking at the code
client.ml:100:
Eio.Buf_read.of_flow ~initial_size ~max_size:max_int conn
is lazy enoughCohttp_eio.Client.read_fixed
gets called it still tries to pull from the socket (?)Eio.Net.with_tcp_connect
says: “[conn] is closed after [f] returns (if it isn't already closed by then).”I tried to replace
read_fixed
with this to see what happens:It fails after saying
+not done reading: 3960
The text was updated successfully, but these errors were encountered: