John Escott (Thu 02/23/06 19:20):
> Apologies in advance that this post has got a bit longer than I expected 
> when I started ...
> 
> I'm using Wheel::Run to run a program in a child process and catch stdout 
> and stderr. This works fine when the program is run in a terminal, but 
> when I daemonize it using Proc::Daemon, something strange happens -- the 
> stdout and stderr from the child "disappears". I've searched the archives 
> and the effect is the same as that described by Matthew Hicks in a thread 
> of similar name back in Sept 2005, and I've found that his solution also 
> works for me (edit Proc::Daemon to change it to stop it re-opening STDIN 
> to /dev/null. I also found I had to stop it reopening STDERR as well).
> 
> I also see it's in the bug list as #16691 (from Chris Fedde, with a 
> different work around).
> 
> This prompted me to try a third course of action: change Proc::Daemon so 
> it only runs POSIX::close for file descriptors 3 and up and not for 0, 1, 
> 2. Change:
>     foreach $i (0 .. OpenMax) { POSIX::close($i); }
> to
>     foreach $i (3 .. OpenMax) { POSIX::close($i); }
> This also fixes the problem, so I'm guessing that there's some interaction 
> between POSIX::close and a subsequent perl open that causes the problem. 
> (The perl FAQ makes no mention of POSIX::close in its section on 
> daemonization).
> 
> Not sure if this is a Linux thing or what? (I'm using RHEL3, perl 5.8.0, 
> POE 0.33).
> 
> However, in the course of investigating this, I've found a simple 
> illustration of the problem. I started with the "Child Processes 2" 
> example from the cookbook 
> (http://poe.perl.org/?POE_Cookbook/Child_Processes_2). This example runs 
> "ls -1 /" as the child.
> I added the following 6 lines before the POE::Session->create:
> 
>         use Proc::Daemon;
>         # Proc::Daemon::init();
>         open STDOUT, ">$ENV{HOME}/xx.stdout" or die "! 
> $ENV{HOME}/xx.stdout : $!";
>         open STDERR, ">$ENV{HOME}/xx.stderr" or die "! 
> $ENV{HOME}/xx.stderr : $!";
>         open O, ">$ENV{HOME}/xx.log" or die "! $ENV{HOME}/xx.log : $!";
>         select O; $| = 1;
> 
> I also added another argument to the program that's run to make it give an 
> error message on stderr, so it now reads:
> 
>       ( Program => [ "/bin/ls", "-1", "/", "/non-exist" ],    # Program to 
> run.
>  
> When I run it, it produces the listing of / in xx.log. The lines are 
> prefixed by "STDOUT: ", showing that they were written by the 
> got_child_stdout() event handler and the error line for /non-exist is 
> prefixed "STDERR: ". xx.stdout is an empty file and xx.stderr contains a 
> line "Child process PID:xxx reaped:".
> 
> If I uncomment the Proc::Daemon::init() line and run again, the effect is 
> different. This time, xx.log just contains the line "child closed." (from 
> the got_child_close() event handler). xx.stdout contains the ls of /. And 
> xx.stderr contains a whole load of lines saying "Child process PID:0 
> reaped:" (over 88000 of them in one case, over 1400 on another machine). 
> The error line for /non-exist is buried in the middle somewhere and the 
> file ends with the reaped message for the real child pid.
> 
> This seems to imply that somehow the child gets the original 
> pre-daemonization stdout and stderr, although I'm not sure how, after 
> they've been POSIX::closed and re-opened in Proc::Daemon and then piped by 
> Wheel::Run. And it seems that waitpid() keeps returning 0 (instead of -1?) 
> in Resources/Signals.pm, l.156.
> 
> Anyway, applying any of the 3 changes above, fixes the problem.
> 
> best regards, John Escott.
> 

I definitely see the same behaviour on both RHEL3/5.8.7 and FreeBSD/5.8.8.
However, non-daemonized and daemonized outputs are identical using 
Net::Server::Daemonize which is what I've always used for this sort of 
thing.

Zach

Reply via email to