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

I am having a situation that is comlpetely stumping me. The overview is this: I have a perl daemon using Thread::Pool that runs fine if I do not daemonize the process, the worker thread pool starts fine, the main process submits jobs to the pool, everything runs, etc. However, if I daemonize(fork) the process first then it stops dead at initializing the thread pool.

I though at first that this was exclusively a Thread::Pool problem, but I'm not entirely sure. Being relatively new to using threads, is there some common mistake with forking before starting threads that I may be running into? I'm not entirely sure what to ask, but here is some relevant info:

Perl v5.8.0 on Debian Linux

Modules, etc:

use strict; use warnings; #use Proc::Daemon; # tried this also, with the same # results as the snippet below use threads; # Do I even need these since use threads::shared; # Thread::Pool uses 'threads'? use Thread::Pool; use POSIX;
For the kids:
$SIG{CHLD} = sub { while ( POSIX::waitpid(-1,POSIX::WNOHANG) > 0 ) { } + };
The daemonizing snippet:
die "ERROR: unable to fork!! Dying." unless defined (my $child = fork) +; exit 0 if $child; POSIX::setsid(); open(STDIN, "</dev/null"); open(STDOUT, ">/dev/null"); open(STDERR, ">&STDOUT"); chdir '/'; umask (0); $ENV{PATH} = "/bin:/sbin:/usr/bin:/usr/sbin"; return $$;

Normally, it should fork first, then spawn threads and run. However, I have tried starting the thread pool before forking and I get "A thread exited while 3 others were running", though in stracing it I can't find a thread dying with an error. (is it the main proc exiting after forking?) Despite this error, the process continues until it tries to submit a job to the thread pool, then it hangs as before. Here is the last bit of a trace:

1408 open("/usr/lib/perl/5.8.0/auto/Storable/_freeze.al", O_RDONLY|O_ +LARGEFILE) = 11 1408 fstat64(11, {st_mode=S_IFREG|0644, st_size=706, ...}) = 0 1408 old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONY +MOUS, -1, 0) = 0x402af000 1408 read(11, "# NOTE: Derived from ../../lib/S"..., 4096) = 706 1408 read(11, "", 4096) = 0 1408 close(11) = 0 1408 munmap(0x402af000, 4096) = 0 1408 brk(0x8ab5000) = 0x8ab5000 1408 brk(0x8abd000) = 0x8abd000 1408 kill(1405, SIGRTMIN) = -1 ESRCH (No such process) 1408 rt_sigprocmask(SIG_SETMASK, NULL, [RTMIN], 8) = 0 1408 rt_sigsuspend([]

I've no idea if the trace is helpful or not...
I feel as though I'm missing somthing basic here but I cannot seem to figure out what it is...or maybe this is exclusively a Thread::Pool problem (ahem, or my own). There are way too many possibilities to bring up in one post, but hopefully this will be enough to ring a bell with someone. Thanks in advance, good luck deciphering my confusion :)

mike

edited: Tue Dec 3 16:12:33 2002 by jeffa - added reamore tag

Replies are listed 'Best First'.
Re: daemonizing and threads
by pg (Canon) on Dec 02, 2002 at 23:16 UTC
    I played with Thread::Pool, and seems fine. What I did is:
    1. fork a new process
    2. exit the main process
    3. in the forked process, initialize Thread::Pool
    4. the forked process start an endless loop to dispatch jobs to thread pool. The job my threads do is simple, just take two numbers, and return the sum.
    Two points:
    1. It sounds to me more logical to fork first, and then initialize the Thread::Pool, indeed the Thread::Pool object has nothing to do with the main process, from the design view, it should be contained in a smaller as possible scope.
    2. The error msg you got saying exit when other threads running, is because you exited main process, without first stop or join all threads.
      I totally agree that one would almost always fork before threading. I had only reversed it for testing.

      As for the error message, I assumed that it was result of the main process exiting. After you pointed that out, I thought about it though... The main process /should/ be dead before the threads even start. Since that does not appear to be the case, would that imply that indeed the original parent is exiting late, perhaps before the child has acheived independence?

      Thanks much for the input.

      mike

Re: daemonizing and threads
by Zaxo (Archbishop) on Dec 03, 2002 at 01:10 UTC

    The line exit 0 if $child; indeed exits the parent after fork. That is normal for daemon spawning. Is the problem intermittent, perhaps half the time? It may be that the parent sometimes exits too quickly, causing SIGHUP to be sent to the child before it establishes its independence. Setting $SIG{HUP} to IGNORE or an empty handler before fork should fix that.

    Customarily, a daemon's SIGHUP handler causes it to reread configuration files and reconfigure accordingly. That can be set up after the daemon is well started.

    You probably should get your daemonizing out of the way before threading. Have you considered daemonizing in a BEGIN block, before use threads; is even seen?

    After Compline,
    Zaxo