Thread

Posted on Thu Aug 28 22:14:43 2008 by ssinyagin
reopening STDERR in parent process
The Torrus collector reopens STDERR upon SIGHUP: Line 113 in source
my $rotateLogs = sub { Info('Caught SIGHUP. Reopening log file'); close( STDERR ); open( STDERR, ">>$logfile" ); $| = 1; };
After assigning this signal handler, the collector spawns a child thread. The child prints its debugging and error messages to STDERR. The problem appeared that when the logfile is moved and SIGHUP is sent to the process, only the parent process starts to write to the new file. The child thread continues writing to the old file.

How can I organize the logging so that the file rotation is still possible? Would log4perl be of any help?
Direct Responses: 8689 | Write a response
Posted on Thu Aug 28 22:51:43 2008 by jdhedden in response to 8688
Re: reopening STDERR in parent process
This is not really an effective forum for discussing this issue - it's intended for the 'threads' module itself, and not module specific questions like this. Perhaps you could try the Torrus developers, or the Torrus wiki.
Direct Responses: 8691 | Write a response
Posted on Thu Aug 28 23:23:03 2008 by ssinyagin in response to 8689
Re: reopening STDERR in parent process
this is indeed a threads-specific question. I don't know what happens to STDERR when a thread is created, and what happens to it when the main thread reopens STDERR. I think this is the best place to ask for advice. In the Torrus developers community, I'm actually THE main developer :-)
Direct Responses: 8697 | Write a response
Posted on Fri Aug 29 15:22:43 2008 by jdhedden in response to 8691
Re: reopening STDERR in parent process
Each thread gets its own perl interpreter which is a clone of its parent when the the thread was created. As such, all file handles (including STDERR) are duplicated when a thread is created. Because of this, closing and reopening STDERR in one thread does not affect STDERR in other threads.

Also, signals are not propagated to each thread. Under Cygwin, for example, only the main thread interpreter gets them. (It may be that under other OS's the currently active interpreter will act on a signal. You'll have to test this to be sure.)

Using threads v1.27 or later, you can send signals to threads. The code below may work for you:
$SIG{'USR1'} = $rotateLogs; $SIG{'HUP'} = sub { # Signal all (running, non-detached) threads to rotate logs if ($threads::threads) { $_->kill('USR1') foreach threads->list('running'); } # Rotate logs in main thread $rotateLogs->(); };
Note, however, that the list of running threads does not include detached threads. You'll need to track them yourself, if needed.
Direct Responses: 8698 | 8700 | Write a response
Posted on Sat Aug 30 01:03:27 2008 by ssinyagin in response to 8697
Re: reopening STDERR in parent process
thanks, that explains a lot. Actually the child threads are detached, but I'll handle that.

in some archives at perlmonks someone said that file descriptors are global across all threads, and that's what confused me in my understanding of what's going on. Also it looks like when the thread is created, it does not inherit the value of $| - the messages written by the child thread are sometimes cut by the buffering.
I think the most reliable thing would be instead of printing to STDERR in the child thread, push the error messages into a queue and let the main thread pop the messages and print them to the main thread's STDERR.
Write a response
Posted on Sat Aug 30 13:19:21 2008 by ssinyagin in response to 8697
Re: reopening STDERR in parent process
I think the best way would be to change the logging from STDERR to Syslog. Then it should work fine from every thread
Write a response