Some years ago, before the Net::Server and Net::Daemon modules were on CPAN, a friend asked me to write him a simple daemon that would sniff out servers for Quake, Unreal, etc. That is, one tool to do all of these types, and provide a way for him to connect and get the list, etc. etc. Of course, since then people have written much more feature-ful tools like this, some of them even in C :-). What I took away from the experience, though, is the following subroutine. Since he planned on having this thing run for days at a time, I wanted it to daemon-ize itself just as cleanly as sendmail, inetd, or any other legacy daemon written in C. So I turned to my trusty copy of "Advanced UNIX Programming" by the (late) great W. R. Stevens, and churned out this piece.

What you see here is a much more literate version, one that has some commentary sprinkled around, and some better attention to indentation and such, for the sake of readability. The one (optional) parameter it takes at invocation is a simple boolean of whether to die on errors or not. Unless explicitly specified, the default is to die when an error occurs. When the function returns (error-free), the caller may feel confident that they are now well and properly backgrounded. STDIN, STDOUT and STDERR are no longer available to you, but they are available to be reopened onto any files you like.

This could maybe be made more efficient or more compact, but soon after this was when Net::Daemon came out, and soon after that Net::Server. If you have real server-implementation needs, I recommend one of those (I provide support for Net::Server natively in my RPC::XML package). But if you have a simpler task for which you want to background and not worry about terminal-related and process-group-related signals and issues, this may hopefully be of use. Enjoy.

Update: Added a chdir to root.

--rjray

sub become_daemon { my $dont_die = shift || 0; my ($child, $sig); $child = fork; if (defined $child) { exit 0 if $child; } else { $dont_die && return "Error in fork: $!"; die "$0 died in fork: $!, dead"; } # # First-generation child. # setpgrp; close(STDIN); close(STDOUT); close(STDERR); chdir '/'; umask 0; for (qw(TSTP TTIN TTOU)) { $SIG{$_} = 'IGNORE' if (exists $SIG{$_} +) } # # In case of SysV, re-spawn to avoid danger of re-acquiring a cont +rol # terminal. Now the child is not the pgrp leader. # $sig = $SIG{HUP}; $SIG{HUP} = 'IGNORE'; $child = fork; if (defined $child) { exit 0 if $child; } elsif ($child) { $dont_die && return "Error in (1st-generation child) fork: $!" +; die "$0 (1st-generation child) died in fork: $!, dead"; } # # Restore HUP (which will probably be set later on, anyway) and re +turn. # $SIG{HUP} = $sig; return; }

In reply to Forking the polite way by rjray

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.