views:

406

answers:

5

I wrote a PHP program that hooks into syslog-ng (via syslog-ng.conf) and it's basically this:

while (!feof(STDIN)) {
    $input = fgets(STDIN);
    process($input);
}
cleanup();

where process() and cleanup() are defined by me.

The problem I am facing is that cleanup(2) is never called and I need it to be executed before the program exits.

I have tried to catch SIGTERM, SIGHUP and SIGPIPE using pcntl_signal() and that part of the application seems to work fine (if I use kill -1 on the PHP process, my signal handler gets called and it runs cleanup()), but it appears that I am not getting those meessages from syslog-ng.

I have tried setting STDIN to non-blocking, thinking that PHP wouldn't call the signal handlers because the stream was blocking. That didn't work either, my signal handlers wouldn't get called.

How do I know when syslog-ng is about to stop my application, so I can do some cleanup?

Thanks, Tom

UPDATE: I've tried to catch all the signals, from 1 to 31 and it still doesn't receive anything when syslog-ng is restarted (or killed with SIGTERM).

A: 

This is a shot in the dark, but try re-writing your loop as follows:

do {
   $input = fgets(STDIN);
   process( $input );
while ( !feof( STDIN ) ) {
cleanup();

The idea being that when syslog-ng closes stdout (assuming it does?), fgets will attempt to read and actually reach EOF.

Phil
In the case mentioned, wouldn't your logic better suited in a do{ }while() ?
Kevin Peno
Agreed - much cleaner.
Phil
I would probably add an if around the fgets call as well, since fgets returns false on failure `if( ( $input = fgets(STDIN); ) === FALSE ) break;`
Kevin Peno
feof should not be used in a do/while, as feof needs to be checked *before* one reads from a file. Empty files are at EOF upon fopen. $ touch testfile $ ls -l testfile -rw-r--r-- 1 clint staff 0 Nov 9 08:43 testfile $ php -r '$x = fopen("testfile", "r"); var_dump($x); $y = feof($x); var_dump($y);' resource(5) of type (stream) bool(false)
This is true, however fgets should return false in that case as well.
Kevin Peno
+3  A: 

Perhaps try to register cleanup() as a PHP shutdown function, like so:

function cleanup(){}
register_shutdown_function("cleanup");

In theory this will cause php to execute the function prior to exiting. This may not work when used with forced halt options (like kill) though, so it's (yet another) shot in the dark.

I hope you find something that works though. I'd be interested in learning the results as well.

Edit: I'm glad this worked out for you!

Kevin Peno
I think you mean `register_shutdown_function('cleanup');`This is a cool function, thanks for pointing that out!
memnoch_proxy
haha, thanks for pointing that out. And, np.
Kevin Peno
I accidentally downvoted you. Sorry, your answer was correct. Try editing it, so I may reverse the vote.
Tom
A: 

Abrupt termination of your PHP script without proper cleanup is probably because a runtime error happens (for example, because your process() is not ready to handle an empty string returned by by fgets() when it reaches EOF).

Enable PHP error logging to see what happens.

Alexey Feldgendler
A: 
Douglas Muth
That still doesn't help when dealing with SIGTERM, sorry.
Tom
A: 

Does PHP thoughtfully handle your signals for you? Try prototyping in another language that you have more control.

Epsilon Prime