##---------------------------------------------------------------------------## ## File: ## @(#) Daemon.pm 1.2 99/04/17 01:02:34 ## Author: ## Earl Hood earlhood@usa.net ##---------------------------------------------------------------------------## ## Copyright (C) 1997-1999 Earl Hood, earlhood@usa.net ## All rights reserved. ## ## This program is free software; you can redistribute it and/or ## modify it under the same terms as Perl itself. ##---------------------------------------------------------------------------## package Proc::Daemon; use strict; use vars qw( $VERSION @ISA @EXPORT_OK ); use Exporter; @ISA = qw( Exporter ); $VERSION = "0.02"; @EXPORT_OK = qw( Fork OpenMax ); ##---------------------------------------------------------------------------## use Carp; use POSIX; ##---------------------------------------------------------------------------## ## Fork(): Try to fork if at all possible. Function will croak ## if unable to fork. ## sub Fork { my($pid); FORK: { if (defined($pid = fork)) { return $pid; } elsif ($! =~ /No more process/) { sleep 5; redo FORK; } else { croak "Can't fork: $!"; } } } ##---------------------------------------------------------------------------## ## OpenMax(): Return the maximum number of possible file descriptors. ## If sysconf() does not give us value, we punt with our own value. ## sub OpenMax { my $openmax = POSIX::sysconf( &POSIX::_SC_OPEN_MAX ); (!defined($openmax) || $openmax < 0) ? 64 : $openmax; } ##---------------------------------------------------------------------------## ## Init(): Become a daemon. ## sub Init { my $oldmode = shift || 0; my($pid, $sess_id, $i); ## Fork and exit parent if ($pid = Fork) { exit 0; } ## Detach ourselves from the terminal croak "Cannot detach from controlling terminal" unless $sess_id = POSIX::setsid(); ## Prevent possibility of acquiring a controling terminal if (!$oldmode) { $SIG{'HUP'} = 'IGNORE'; if ($pid = Fork) { exit 0; } } ## Change working directory chdir "/"; ## Clear file creation mask umask 0; ## Close open file descriptors foreach $i (0 .. OpenMax) { POSIX::close($i); } ## Reopen stderr, stdout, stdin to /dev/null open(STDIN, "+>/dev/null"); open(STDOUT, "+>&STDIN"); open(STDERR, "+>&STDIN"); $oldmode ? $sess_id : 0; } *init = \&Init; ##---------------------------------------------------------------------------## 1; __END__ =head1 NAME Proc::Daemon - Run Perl program as a daemon process =head1 SYNOPSIS use Proc::Daemon; Proc::Daemon::Init; =head1 DESCRIPTION This module contains the routine B<Init> which can be called by a perl program to initialize itself as a daemon. A daemon is a process that runs in the background with no controlling terminal. Generally servers (like FTP and HTTP servers) run as daemon processes. However, do not make the mistake that a daemon == server. The B<Proc::Daemon::Init> function does the following: =over 4 =item 1 Forks a child and exits the parent process. =item 2 Becomes a session leader (which detaches the program from the controlling terminal). =item 3 Forks another child process and exits first child. This prevents the potential of acquiring a controlling terminal. =item 4 Changes the current working directory to "/". =item 5 Clears the file creation mask. =item 6 Closes all open file descriptors. =back You will notice that no logging facility, or other functionality is performed. B<Proc::Daemon::Init> just performs the main steps to initialize a program as daemon. Since other funtionality can vary depending on the nature of the program, B<Proc::Daemon> leaves the implementation of other desired functionality to the caller, or other module/library (like B<Sys::Syslog>). There is no meaningful return value B<Proc::Daemon::Init>. If an error occurs in B<Init> so it cannot perform the above steps, than it croaks with an error message. One can prevent program termination by using eval. =head1 OTHER FUNCTIONS B<Proc::Daemon> also defines some other functions. These functions can be imported into the callers name space if the function names are specified during the B<use> declaration: =head2 Fork B<Fork> is like the built-in B<fork>, but will try to fork if at all possible, retrying if necessary. If not possible, B<Fork> will croak. =head2 OpenMax B<OpenMax> returns the maximum file descriptor number. If undetermined, 64 will be returned. =head1 NOTES =over 4 =item * B<Proc::Daemon::init> is still available for backwards capatibilty. However, it will not perform the double fork, and will return the session ID. =back =head1 AUTHOR Earl Hood, earlhood@usa.net http://www.oac.uci.edu/indiv/ehood/ =head1 CREDITS Implementation of B<Proc::Daemon> derived from the following sources: =over 4 =item * B<Advanced Programming in the UNIX Environment>, by W. Richard Stevens. Addison-Wesley, Copyright 1992. =item * B<UNIX Network Progamming>, Vol 1, by W. Richard Stevens. Prentice-Hall PTR, Copyright 1998. =back =head1 DEPENDENCIES B<Proc::Daemon> depends on the following modules: B<Carp>, B<POSIX>. =head1 SEE ALSO L<POSIX>, L<Sys::Syslog> =cut