caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Dave Benjamin <dave@ramenlabs.com>
To: caml-list@inria.fr
Subject: Re: [Caml-list] Closing all open file descriptors
Date: Fri, 14 Sep 2007 00:32:10 -0700	[thread overview]
Message-ID: <46EA38FA.8010201@ramenlabs.com> (raw)
In-Reply-To: <20070914164810.39a4dcda.mle+ocaml@mega-nerd.com>

Erik de Castro Lopo wrote:
> Dave Benjamin wrote:
> 
>> Did your program "daemonize" at all, then? Or did you use daemontools?
> 
> Yes, it called Unix.fork and then in the child called Unix.setsid.
> 
> Err, what's daemontools?

daemontools is a service management framework by D. J. Bernstein which 
those pages you linked were partially in reference to. The basic 
philosophy is that you don't write daemons at all; you write regular 
programs that read from stdin and write to stdout. You don't fork, you 
don't setsid, you don't worry about the environment and you don't keep 
track of PID files.

(IMHO, that's why they're so worked up about closing file descriptors. 
They're trying to get daemons to stop being daemons so they can be 
controlled by daemontools, and this is one of the sticking points.)

The daemontools style is actually a little bit like functional 
programming in its use of wrapper programs. A typical daemontools 
solution to the file descriptor closing problem would be to write a tiny 
C program that closes the file descriptors and then forks and execs its 
argument, like this:

closefds mydaemon arg1 arg2 ...

where "closefds" closes the file descriptors and then runs "mydaemon" 
with the supplied arguments. This way, "closefds" would just be another 
reusable tool.

Incidentally, Linux comes with a "setsid" program that does the same 
think with fork and setsid. It doesn't seem to be available for BSD, 
though (though "nohup" is, which is similar as well).

> My program has passes around a logging function of type "string -> unit".
> If it not a daemon it uses print_endline for logging and if it is a daemon 
> it uses a wrapper around syslog (via the debian/ubuntu libsyslog-ocaml-dev)
> package.

Makes sense to me.

>> Yeah, the whole operation could be done in a C function too, and 
>> probably wouldn't be much more code to write.
> 
> My daemon is only tiny, but I'm, still glad its in Ocaml.

I agree, overall the Unix module is pretty nice to use.

Here's a port of the "daemonize" C function described in APUE to OCaml, 
and it's where my earlier code example came from:

(* Based on Adv. Programming in the UNIX Environment, 2nd Ed. *)

#use "topfind";;
#require "unix";;
#require "syslog";;

open Printf

let daemonize cmd =
   (* Clear file creation mask. *)
   ignore (Unix.umask 0);

   (* Become a session leader to lose controlling TTY. *)
   if Unix.fork () > 0 then exit 0;
   ignore (Unix.setsid ());

   (* Ensure future opens won't allocate controlling TTYs. *)
   Sys.set_signal Sys.sighup Sys.Signal_ignore;
   if Unix.fork () > 0 then exit 0;

   (* Change the current working directory to the root so
      we won't prevent file systems from being unmounted. *)
   Unix.chdir "/";

   (* Close all open file descriptors. *)
   for fd = 0 to 1024 do
     try Unix.close (Obj.magic fd : Unix.file_descr)
     with Unix.Unix_error _ -> ()
   done;

   (* Attach file descriptors 0, 1, and 2 to /dev/null. *)
   let fd0 = Unix.openfile "/dev/null" [Unix.O_RDWR] 0o666 in
   let fd1 = Unix.dup fd0 in
   let fd2 = Unix.dup fd0 in

   (* Initialize the log file. *)
   let log = Syslog.openlog cmd in
   if fd0 <> Unix.stdin || fd1 <> Unix.stdout || fd2 <> U
     begin
       Syslog.syslog log `LOG_ERR
         (sprintf "unexpected file descriptors %d %d %d"
            (Obj.magic fd0 : int)
            (Obj.magic fd1 : int)
            (Obj.magic fd2 : int));
       exit 1
     end;
   log

let () =
   let log = daemonize "daemonize" in
   Syslog.syslog log `LOG_INFO "Starting daemon";
   Unix.sleep 10;
   Syslog.syslog log `LOG_INFO "Farewell"

Cheers,
Dave


  reply	other threads:[~2007-09-14  7:33 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-09-13 22:56 Dave Benjamin
2007-09-14  1:04 ` [Caml-list] " Erik de Castro Lopo
2007-09-14  6:35   ` Dave Benjamin
2007-09-14  6:48     ` Erik de Castro Lopo
2007-09-14  7:32       ` Dave Benjamin [this message]
2007-09-14  6:33 ` David Allsopp
2007-09-14  6:41   ` Dave Benjamin
2007-09-14 10:54     ` Andre Nathan
2007-09-14 10:00   ` Mattias Engdegård
2007-09-14 20:31     ` Dave Benjamin
2007-09-14 21:52       ` Oliver Bandel
2007-09-14 22:12         ` Markus E L
2007-09-15  9:15           ` Oliver Bandel
2007-09-15  9:26             ` Erik de Castro Lopo
2007-09-15 10:43               ` Oliver Bandel
2007-09-15 11:36                 ` Mattias Engdegård
2007-09-15 11:57                   ` Oliver Bandel
2007-09-15 14:27                     ` Markus E L
2007-09-15 12:16                   ` Oliver Bandel
2007-09-15 14:29                     ` Markus E L
2007-09-15 18:04                       ` skaller
2007-09-15 14:17                   ` Markus E L
2007-09-15 14:16                 ` Markus E L
2007-09-15 15:58                   ` Eric Cooper
2007-09-15 16:17                     ` Markus E L
2007-09-15 18:33                       ` skaller
2007-09-15 17:44                   ` skaller
2007-09-14 10:10 ` Gerd Stolpmann
2007-09-14 11:56 ` Oliver Bandel
2007-09-17 11:00 ` Ville-Pertti Keinonen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=46EA38FA.8010201@ramenlabs.com \
    --to=dave@ramenlabs.com \
    --cc=caml-list@inria.fr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).