swh:1:snp:d7f1b9eb7ccb596c2622c4780febaa02549830f9
Raw File
Tip revision: ad58ae426e7e9200530d18bf439d02657503426c authored by fclement on 23 November 2010, 11:33:06 UTC
Ignore all generated files.
Tip revision: ad58ae4
server_process.ml
(***********************************************************************)
(*                                                                     *)
(*                          OCamlP3l                                   *)
(*                                                                     *)
(* (C) 2004-2007                                                       *)
(*             Roberto Di Cosmo (dicosmo@dicosmo.org)                  *)
(*             Zheng Li (zli@lip6.fr)                                  *)
(*             Pierre Weis (Pierre.Weis@inria.fr)                      *)
(*             Francois Clement (Francois.Clement@inria.fr)            *)
(*                                                                     *)
(* Based on original Ocaml P3L System                                  *)
(* (C) 1997 by                                                         *)
(*             Roberto Di Cosmo (dicosmo@ens.fr)                       *)
(*             Marco Danelutto (marcod@di.unipi.it)                    *)
(*             Xavier Leroy  (Xavier.Leroy@inria.fr)                   *)
(*             Susanna Pelagatti (susanna@di.unipi.it)                 *)
(*                                                                     *)
(* This program is free software; you can redistribute it and/or       *)
(* modify it under the terms of the GNU Library General Public License *)
(* as published by the Free Software Foundation; either version 2      *)
(* of the License, or (at your option) any later version.              *)
(*                                                                     *)
(* This program is distributed in the hope that it will be useful,     *)
(* but WITHOUT ANY WARRANTY; without even the implied warranty of      *)
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the       *)
(* GNU Library General Public License for more details.                *)
(*                                                                     *)
(***********************************************************************)

(* $Id: server_process.ml,v 1.4 2007-01-23 15:50:04 weis Exp $ *)

open Printf;;
open Unix;;
open Basedefs;;

(* An output function for debugging *)

let debug ?(mask = 1) f =
  if !dbg && mask land !dbgmask > 0 then (f (); print_newline());;

(* Print context for debugging *)
let context chan =
  fprintf chan "PID %d (on %s)" (getpid()) (gethostname());;

let timedcontext chan =
  fprintf chan "PID %d(%f) [on %s]" (getpid()) (gettimeofday()) (gethostname());;

(* This function makes a reference local to the process/thread *)

let mklocalref v = let r = ref v in (fun () -> !r),(fun v -> r:= v);;  (* id on processes *)

(* Establish a server on an input socket, keeping track of sons and exiting when no sons left *)

(* WARNING: the usage of inet_addr_any is dangerous: on a machine with several interfaces, this
   does not necessarily sets up the server on the network we want *)

let establish_smart_server servfun =
  let sock = socket PF_INET SOCK_STREAM 0 in
  begin
    match !dynport with
      true -> bind sock (ADDR_INET(inet_addr_any,0));
        let port = match Unix.getsockname sock with 
	  | ADDR_INET(_,x) -> x | _ -> assert false
        in printf "dynport=%4d\n" port; print_newline()
    | false ->  bind sock (ADDR_INET(inet_addr_any,p3lport))
  end;
  listen sock 3;
  let child_count = ref 0 in
  let rec reap_children signo =
    let (pid, status) = waitpid [WNOHANG] (-1) in
    if pid <> 0 then begin
	debug (fun () -> printf "%t: PID %d terminated" context pid; print_newline());
      decr child_count;
      if !child_count = 0 then begin
        debug (fun () -> printf "%t: no more children, exiting" context; print_newline());
        exit 0
      end;
      reap_children signo
    end in
  let _ = Sys.signal Sys.sigchld (Sys.Signal_handle reap_children) in ();
  while true do
    try
      let (s, caller) = accept sock in
      incr child_count;
      if fork() = 0 then begin
        servfun s caller;
        begin
	  try
	    debug(fun () -> printf "server_process: closing channel %s -> %s.\n" (name_of_descr ~peer:false s) (name_of_descr s));
	    Unix.close s
	  with _ -> debug(fun () -> printf "server_process: channel already closed!");  (); (* protect in case the server already closed the channel! *)
	end;
        exit 0
      end
    with Unix_error(EINTR, _, _) -> debug (fun () -> printf "server_process: received EINTR")
  done;;

let spawn func arg =
  let i = Unix.fork () in
  if i = 0 then (func arg; exit 0);;
back to top