Skip to content
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_lwt_unix.Server: Do not leak fd serving potentially never ending bodies #982

Merged
merged 2 commits into from
Jun 7, 2023

Conversation

pirbo
Copy link
Contributor

@pirbo pirbo commented Jun 1, 2023

Please tell me if I should be doing what I do in a complete different way (and c70ad81 makes me think I do because Cohttp.Connection are useful in my case)

I want to use Cohttp to serve Server Sent Events (aka stream of things living as long as there is a client to receive them) and the way I implement them follows the sketch of 3226fdd but I realize that without this patch "Cohttp" never close the connections:

  • I dune exec cohttp-lwt-unix/examples/server_sent_event_lwt.exe in one terminal and in an other I can see
$ lsof -p PID | wc -l
15
$ curl http://localhost:8800
Not found: //localhost:8800/
$ lsof -p PID | wc -l
15
$ curl http://localhost:8800/lol
Not found: //localhost:8800/lol
$ lsof -p PID | wc -l
15

but

$ curl http://localhost:8800/tic
Tic
Tic
^C
$ lsof -p PID | wc -l
16
$ curl http://localhost:8800/tic
Tic
^C
$ lsof -p PID | wc -l
17

And obviously, if you wait to drain the infinite body of the reply before calling conn_closed that would terminates it, it would take a while...

So, here I'm (maybe naively) swapping the 2.

>>= function
| Ok () -> Lwt.return_unit
| Ok () ->
if keep_alive then handle_client oc
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If handle_client fails to read here we will never drain the body. This was related to an issue that led to a DOS: #977

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not against this change, but we need to make it in such a way as to not re-open #978

The rule of thumb was that there shoudl be no infinite body, and if tje server has it, there should be a server-side way to prevent it. Maybe in this case it could be more suitable to use https://github.com/mirage/ocaml-cohttp/blob/master/cohttp-server-lwt-unix/src/cohttp_server_lwt_unix.mli which has a finer control on the body?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I know, it is rather undocumented unfortunately, it is still a work in progress)

Copy link
Contributor Author

@pirbo pirbo Jun 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cohttp-server-lwt-unix looks promising and clearly it may be the way, going forward.

That being said, I think this patch does not reopen #978: If IO.catch [...]returns Ok (), it means that Response.write [...] succeed which means that the Body.write_body [...] have all been successfully completed so this body of that response fully consumed and there is no more things to drain here, isn't it ?

Edit: I forgot to thank you for your reactivity, Thank you!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, I went too fast there. I think it is fine. I wonder if we can add a test case, some kind of update of https://github.com/mirage/ocaml-cohttp/pull/977/files#diff-efd414a623c8f96d3b50c273441dd9a953d0d721a3369f4588ba01a3d1a0710d perhaps using the example you linked.

@pirbo pirbo requested a review from mseri June 2, 2023 08:29
@mseri
Copy link
Collaborator

mseri commented Jun 2, 2023

Please add a changelog entry

@mseri
Copy link
Collaborator

mseri commented Jun 7, 2023

If I am not mistaking anything, this seems fine to me. I also spent some time testing it locally and it seems all right

@mseri mseri merged commit ee1ba0b into mirage:master Jun 7, 2023
15 of 19 checks passed
@pirbo pirbo deleted the server_sent_event_ready branch June 7, 2023 13:01
mseri added a commit that referenced this pull request Jul 7, 2023
mseri added a commit to mseri/opam-repository that referenced this pull request Aug 8, 2023
…p-mirage, cohttp-lwt, cohttp-lwt-unix, cohttp-lwt-jsoo, cohttp-eio, cohttp-curl, cohttp-curl-lwt, cohttp-curl-async, cohttp-bench and cohttp-async (6.0.0~alpha2)

CHANGES:

- cohttp-lwt: Do not leak exceptions to `Lwt.async_exception_hook`. (mefyl mirage/ocaml-cohttp#992, mirage/ocaml-cohttp#995)
- http.header, cohttp, cohttp-eio: remove "first" and "move_to_first" and the special treatment of the "host" header (mseri mirage/ocaml-cohttp#988, mirage/ocaml-cohttp#986)
- http.header: introduce "iter_ord" to guarantee iteration following the order of the entries in the headers (mseri mirage/ocaml-cohttp#986)
- do not omit mandatory null Content-Length headers (mefyl mirage/ocaml-cohttp#985)
- cohttp-async, cohttp-curl-async: compatibility with core/async v0.16.0 (mseri, dkalinichenko-js mirage/ocaml-cohttp#976)
- cohttp-lwt server: call conn_closed before drainig the body of response on error (pirbo mirage/ocaml-cohttp#982)
- cohttp-eio: Relax socket interface requirement on `Server.connection_handler`. (mefyl mirage/ocaml-cohttp#983)
mseri added a commit to mseri/opam-repository that referenced this pull request Aug 8, 2023
…p-mirage, cohttp-lwt, cohttp-lwt-unix, cohttp-lwt-jsoo, cohttp-eio, cohttp-curl, cohttp-curl-lwt, cohttp-curl-async and cohttp-async (6.0.0~alpha2)

CHANGES:

- cohttp-lwt: Do not leak exceptions to `Lwt.async_exception_hook`. (mefyl mirage/ocaml-cohttp#992, mirage/ocaml-cohttp#995)
- http.header, cohttp, cohttp-eio: remove "first" and "move_to_first" and the special treatment of the "host" header (mseri mirage/ocaml-cohttp#988, mirage/ocaml-cohttp#986)
- http.header: introduce "iter_ord" to guarantee iteration following the order of the entries in the headers (mseri mirage/ocaml-cohttp#986)
- do not omit mandatory null Content-Length headers (mefyl mirage/ocaml-cohttp#985)
- cohttp-async, cohttp-curl-async: compatibility with core/async v0.16.0 (mseri, dkalinichenko-js mirage/ocaml-cohttp#976)
- cohttp-lwt server: call conn_closed before drainig the body of response on error (pirbo mirage/ocaml-cohttp#982)
- cohttp-eio: Relax socket interface requirement on `Server.connection_handler`. (mefyl mirage/ocaml-cohttp#983)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants