Hello!

( wow, it's been 5! years since I last logged into perlmonks... ah, memories )

Ok, anyhow - I'm just getting back into perl again after a pretty long hiatus, and I hope some of you kind monks can help me out with a question/problem.

I've written a daemonizer in perl - for educational purposes - and now I'm trying to make it more useful by modularizing it. I still got the hang of oop in perl, but I'm lacking the camel book, and I need to know how best to get this thing to work as a module that can be easily instantiated by other scripts and/or modules.

The main problem I'm having, is when I run this ( code following, below ), I get errors such as 'SIGTERM handler "sigterm_catcher" not defined.' for each of my signal handlers... how do I get the namespace/context correct for this to work as expected as a module? ( it works just fine when I "unmodularize" it, and just run it as a self-contained script. )

Also, it's obviously coded as a mere module currently - but I'd like to make this into an actual first-class Class; will that be possible, or do the realities of "daemonization" prevent such a thing? Many thanks!

Here is an example/test script that uses my Daemonizer.pm:

#!/usr/bin/perl -w @INC = [ @INC, './' ]; use Daemonizer; Daemonizer::init; while (1) { sleep 20 }
And here is the Daemonizer.pm itself:
package Daemonizer; use strict; use vars qw( @ISA @EXPORT_OK ); use Exporter; @ISA = qw( Exporter ); use IO::Seekable; use File::Basename; use POSIX qw( setsid ); use Sys::Syslog qw( :DEFAULT setlogsock ); my ( $PID, $lckfile ); $lckfile = '/tmp/' . fileparse( $0, qr{\..*} ) . '.pid'; # appease perl taint checking $ENV{'PATH'} = "/bin:/usr/bin"; # setup syslogging setlogsock('unix'); openlog( 'parselogd', 'pid', 'local6'); # setup signal traps $SIG{'INT'} = 'sigint_catcher'; $SIG{'TERM'} = 'sigterm_catcher'; $SIG{'QUIT'} = 'sigquit_catcher'; $SIG{'ABRT'} = 'sigabrt_catcher'; $SIG{'HUP'} = 'sighup_catcher'; # not strictly needed, but... $SIG{'CHLD'} = 'IGNORE'; # define sigtrap routines sub sigterm_catcher { &term('TERM') } sub sigquit_catcher { &term('QUIT') } sub sigabrt_catcher { &term('ABRT') } sub sigint_catcher { &term('INT') } sub sighup_catcher { &term('HUP') } # perl interpreter traps ( semi-dangerous ) $SIG{'__DIE__'} = sub { &crit( "Caught die: $_[0]" ) }; $SIG{'__WARN__'} = sub { syslog( 'err', "warn! $_[0]" ) }; ### cleanup ## ## sub clean { syslog( 'debug', "cleaning up" ); rm_lock() if $lckfile; } ### die elegantly ## ## sub crit { my $msg = shift; syslog( 'err', "CRIT!: $msg" ); syslog( 'err', "Aborting!" ); clean(); syslog( 'err', "Terminating daemon" ); closelog(); undef $SIG{'__DIE__'}; die "$msg"; } ### terminate process ## ## sub term { my $cause = shift; syslog( 'notice', "recieved $cause signal"); if ( $cause eq 'HUP' ) { syslog( 'notice', "Restarting daemon"); clean(); init(); } else { clean(); syslog( 'notice', "Terminating daemon"); exit; } } ### create lock file ## ## sub write_lock { syslog( 'info', "writing lock" ); open( LCK, ">$lckfile" ) or do { crit( "Could not create lock file: $!" ); }; print LCK "$PID\n"; close( LCK ); } ### remove lock file ## ## sub rm_lock { my ( $found_pid ); syslog( 'info', "removing lock" ); if ( -e $lckfile ) { open( LCK, "<$lckfile" ) or crit( "Could not read lock file: $!" ); while( <LCK> ) { chomp; /$PID/ and $found_pid = 1; } close( LCK ); if ( $found_pid ) { unlink $lckfile or syslog( 'warning', "Could not delete lock file: $!" ); } else { syslog( 'warning', "Unable to find pid: $PID" ); } } else { syslog( 'warning', "No lockfile found" ); } } ### initialize and spawn off daemon ## ## sub init { my ( $pid ); # grab current process id $PID = $$; syslog( 'notice', "starting daemon" ); if ( -e $lckfile ) { crit( "lock file exists! daemon may already be running" ); } syslog( 'debug', "initializing" ); # create the lock file write_lock(); # create child process defined( $pid = fork ) or crit( "unable to fork process!: $!" ); # be a nice little daemon and go to your root chdir('/') or crit( "unable to chdir to \'/\'!: $!" ); # say goodbye to our progeny exit if $pid; # redirect filehandles open STDOUT, ">/dev/null" or crit( "unable to write to /dev/null!: $!" ); open STDIN, "/dev/null" or crit( "unable to read from /dev/null!: $!" ); # create new session POSIX::setsid or crit( "unable to create new session!: $!" ); # fully establish our own identity $PID = $$; $0 = fileparse( $0, qr{\..*} ); # rewrite lock with new pid write_lock(); # hairy part is over, finally dissociate stderr open STDERR, '>&STDOUT' or crit( "unable to attach STDERR to STDOUT!: $!" ); # we're on our own now } 1;

In reply to daemon ... oop'ified? by Zarathustra

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.