BMaximus has asked for the wisdom of the Perl Monks concerning the following question:

I'm taking this right out of the "Network Programming With Perl" book. The program refuses to daemonize. Doing nothing it just dies. I know that it does nothing at the moment but this thing should just drop to a daemon and do nothing regardless. No errors either and it doesn't show up on ps -aux.

#!/usr/bin/perl -wT use strict; use POSIX 'setsid'; use IO::File; sub become_daemon { die "Can't fork"unless defined (my $child = fork()); exit 0 if $child; setsid(); open(STDIN, "</dev/null"); open(STDOUT, ">/dev/null"); open(STDERR, ">&STDOUT"); chdir '/'; umask(0); $ENV{PATH} = '/bin:/sbin/usr/bin/:/usr/sbin'; return $$; } sub open_pid_file { my $file = shift; if (-e $file) { # file exists my $fh = IO::File->new($file) || return; my $pid = <$fh>; die "Server already running with PID $pid" if kill 0 => $pid; warn "Removing PID file - unclean shutdown of keeperd?.\n"; die "Can't unlink file $file" unless -w $file && unlink $file; } return IO::File->new($file, O_WRONLY|O_CREAT|O_EXCL,0644) or die "Can't create $file: $!\n"; } use constant PID_FILE => '/var/run/keeperd.pid'; $SIG{TERM} = $SIG{INT} = sub { exit 0; }; my $fh = open_pid_file(PID_FILE); my $pid = become_daemon(); print $fh $pid; close $fh; END { unlink PID_FILE if $pid = $$; }
So why is it just dying?

BMaximus

Replies are listed 'Best First'.
Re: Daemon sub refuses to daemonize. Why?
by chromatic (Archbishop) on May 18, 2001 at 03:59 UTC
    It is working. Your computer's just too fast. Add in a sleep(10) after the become_daemon() call, and you'll be able to see it in your process list.

    Or get really really really fast at hitting Enter. :)

    The last option is to give it something to do after it becomes a daemon. Something besides falling off the end of the program, anyway.

      Should have seen it. It's just ending with nothing to do so there's nothing to keep it around. Basic mistake. *looks sheepish*

      BMaximus
Re: Daemon sub refuses to daemonize. Why?
by converter (Priest) on May 18, 2001 at 04:34 UTC
    A couple of things I noticed here:
    • On my box, /var/run is root.root 0755. This means that writing the pid file should fail for regular users, but it doesn't. A small change to the code allows the detection of the error:
      return IO::File->new($file, O_WRONLY|O_CREAT|O_EXCL,0644) || die "Can't create $file: $!\n";
      Because of or's low precedence, the return statement is evaluated before Perl can check the value returned by IO::File->new. Using || instead allows the check to take place.

    • This line causes a complaint about an insecure dependency:
      die "Server already running with PID $pid" if kill 0 => $pid;
      Insert this code directly above it to untaint $pid:
      if ($pid =~ /^(\d+)$/) { $pid = $1; } else { die "funky pid read from $file!"; }
      Using the || or using an or works either way on my machine. Running it as an unpriviledged user, the daemon dies saying that it doesn't have permission to create the file. However running it as root and the daemon runs without a hitch except for the fact that no pid file is created. When I look in /var/run for the keeperd.pid file its missing. What could be going wrong here? If keeperd couldn't make the file it should be complaining, but there's every indication that it is making the file.

      BMaximus
        If this were my code, I would probably not write it this way to begin with. Instead, I would assign the reference returned by IO::File->new to a scalar then check to make sure it's defined.

        Something like:

        my $fh = IO::File->new($file, O_WRONLY|O_CREAT|O_EXCL,0644); die "Can't create $file: $!\n" unless defined $fh; return $fh;
        Instead of:
        return IO::File->new($file, O_WRONLY|O_CREAT|O_EXCL,0644) or die "Can't create $file: $!\n";