(** raised when a client timeouts *)
-exception Timeout;;
+exception Timeout
-let backlog = 10;;
+let backlog = 10
(** if timeout is given (Some _) @return a new callback which establish
timeout_callback as callback for signal Sys.sigalrm and register an alarm
in
wrap_callback_w_timeout ~callback ~timeout ~timeout_callback
- (** DEPRECATED and no longer visibile in .mli interface, this server has been
- replaced by 'fork'!
- tcp_server which use Unix.establish_server which in turn forks a child for
- each request *)
-let ocaml_builtin ~sockaddr ~timeout callback =
- let timeout_callback signo =
- if signo = Sys.sigalrm then
- exit 2
- in
- Unix.establish_server
- (wrap_callback_w_timeout ~callback ~timeout ~timeout_callback)
- sockaddr
+ (** try to close an outchannel connected to a socket, ignore Sys_error since
+ * this probably means that socket is already closed (e.g. on sigpipe) *)
+let try_close_out ch = try close_out ch with Sys_error _ -> ()
(** like Unix.establish_server, but shutdown sockets when receiving SIGTERM
and before exiting for an uncaught exception *)
let inchan = Unix.in_channel_of_descr s in
let outchan = Unix.out_channel_of_descr s in
server_fun inchan outchan;
- close_out outchan;
- (* The file descriptor was already closed by close_out. close_in
- inchan; *)
+ try_close_out outchan; (* closes also inchan: socket is the same *)
exit 0
with e ->
shutdown_socket suck; (* clean up socket before exit *)
failwith "Can't fork"
done
+ (** tcp_server which forks a new process for each request *)
let fork ~sockaddr ~timeout callback =
let timeout_callback signo =
if signo = Sys.sigalrm then
(wrap_callback_w_timeout ~callback ~timeout ~timeout_callback)
sockaddr
-
(** tcp_server which doesn't fork, requests are server sequentially and in the
same address space of the calling process *)
let simple ~sockaddr ~timeout callback =
callback inchan outchan;
ignore (Unix.alarm 0) (* reset alarm *)
with Timeout -> ());
- close_out outchan (* this close also inchan: socket is the same *)
+ try_close_out outchan (* this close also inchan: socket is the same *)
done
with e -> (* clean up socket before exit *)
shutdown_socket suck;
let suck = init_socket sockaddr in
let callback = init_callback callback timeout in
let callback (i, o) =
- try
- callback i o;
- close_out o
+ (try
+ callback i o
with
- | Timeout -> close_out o
+ | Timeout -> ()
| e ->
- close_out o;
- raise e
+ try_close_out o;
+ raise e);
+ try_close_out o
in
while true do
let (client, _) = nice_unix_accept suck in
Http_threaded_tcp_server.serve callback (inchan, outchan)
done
+ (** @param server an Http_types.tcp_server
+ * @return an Http_types.tcp_server which takes care of ignoring SIGPIPE during
+ * server execution and restoring previous handler when (if ever) the server
+ * returns *)
+let handle_sigpipe server =
+ fun ~sockaddr ~timeout callback ->
+ let old_sigpipe_behavior = Sys.signal Sys.sigpipe Sys.Signal_ignore in
+ server ~sockaddr ~timeout callback;
+ ignore (Sys.signal Sys.sigpipe old_sigpipe_behavior)
+
+let simple = handle_sigpipe simple
+let thread = handle_sigpipe thread
+let fork = handle_sigpipe fork
+