ocaml-cohttp icon indicating copy to clipboard operation
ocaml-cohttp copied to clipboard

create HTTP redirect example

Open avsm opened this issue 8 years ago • 6 comments

The trivial one used by realworldocaml.org to get HTTP->HTTPS fails every so often with exception leakage.

open Lwt
open Printf
open Cohttp
open Cohttp_lwt_unix

(* main callback function *)
let callback con_id ?body req =
  let path = Uri.path (Request.uri req) in
  Server.respond_redirect ~uri:(Uri.of_string ("https://realworldocaml.org" ^ path))  ()

let _ =
  Sys.set_signal Sys.sigpipe Sys.Signal_ignore;
  let conn_closed con_id () = () in
  let spec = { Cohttp_lwt_unix.Server.callback; conn_closed } in
  Lwt_main.run (Cohttp_lwt_unix.Server.create ~address:"0.0.0.0" ~port:80 spec)

It fails sometimes with

# ./redirect.native 
Fatal error: exception Unix.Unix_error(15, "accept", "")

avsm avatar Aug 01 '15 09:08 avsm

On 1 August 2015 12:05:32 EEST, Anil Madhavapeddy [email protected] wrote:

The trivial one used by realworldocaml.org to get HTTP->HTTPS fails every so often with exception leakage.

open Lwt
open Printf
open Cohttp
open Cohttp_lwt_unix

(* main callback function *)
let callback con_id ?body req =
 let path = Uri.path (Request.uri req) in
Server.respond_redirect ~uri:(Uri.of_string
("https://realworldocaml.org" ^ path))  ()

let _ =
 Sys.set_signal Sys.sigpipe Sys.Signal_ignore;
 let conn_closed con_id () = () in
 let spec = { Cohttp_lwt_unix.Server.callback; conn_closed } in
Lwt_main.run (Cohttp_lwt_unix.Server.create ~address:"0.0.0.0" ~port:80
spec)

It fails sometimes with

# ./redirect.native 
Fatal error: exception Unix.Unix_error(15, "accept", "")

The error message is a little confusing, because errno number 15 doesn't make sense in this context, turns out it is EMFILE.

Perhaps conduit should provide a way to limit the number of active accepted connections, and when over limit wait until another conn is closed. Ocsigenserver limits it to about 350 active connections (configurable) IIRC, and then you have plenty file descriptors left to respond to the request. Different OSes have lower uimit defaults (BSD?), so the default should probably be proportional to RLIMIT_NOFILE.

Either way the server should not die due to EMFILE, if it still gets EMFILE from accept then it should wait until one active conn is closed and retry the accept.

Sent from my Android device with K-9 Mail. Please excuse my brevity.

edwintorok avatar Aug 01 '15 12:08 edwintorok

I'm getting EMFILE on my server every so often and it makes the server unresponsive. How do I fix this?

rathereasy avatar Mar 27 '16 15:03 rathereasy

@edwintorok Doesn't your conduit patch help mitigate this?

rgrinberg avatar Mar 27 '16 16:03 rgrinberg

@rathereasy Could you give this a try with the latest version of conduit and see if it helps.

rgrinberg avatar Mar 27 '16 16:03 rgrinberg

@rgrinberg the latest conduit fixes the leak in the OpenSSL-based server, which might help @rathereasy, however the server in this bug is an HTTP one, which can run out of file descriptors if there are too many clients connecting at the same time. The problem in this bug should be mitigated by https://github.com/mirage/ocaml-conduit/pull/116, I'll look into updating that PR.

edwintorok avatar Mar 27 '16 19:03 edwintorok

Could this be related to https://github.com/mirage/ocaml-cohttp/issues/503 ?

mseri avatar Apr 19 '21 09:04 mseri