Question

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).

Was it helpful?

Solution

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!

OTHER TIPS

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.

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.

I can think of a couple of things you can try to troubleshoot this:

1) Make use of PHP's set_error_handler() function.

2) Put the code mentioned above in a try/catch structure, to try and catch any exceptions that might be thrown.

3) When you run that script, make sure you are capturing both the output and standard error. Change the command line to be something like:

/path/to/script 2>&1 >> /path/to/logfile.txt

...that will help you catch errors.

Finally, if it really is a case where PHP isn't able to catch signals, you'll have to do this through a shell script with the trap command. Something like:

#!/bin/sh
#
# This gets run when the script is hit with a signal
#
trap /path/to/script --cleanup
#
# Run our script
#
/path/to/script 2>&1 >> /path/to/logfile.txt

If there's specific data in the script that cleanup() needs, then you'll have to see about serializing the data and writing it to disk for the cleanup script to read.

Good luck!

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top