18

I want to insure that there are no race conditions introduced by using a custom PHP error handler. To that end I want to know if I can rely on error_log() or if I need to use some other file-locking method to insure errors are logged correctly.

How does the default PHP error handler work? Is it safe from race conditions?

For example, do I have to lock the file (which might cause errors to be lost in this simple version)

function log_error($message)
{
    if(! $fp = @fopen('/path/to/error.log', 'a'))
    {
        return FALSE;
    }

    flock($fp, LOCK_EX);
    fwrite($fp, $message);
    flock($fp, LOCK_UN);
    fclose($fp);

    return TRUE;
}

or can I just call error_log?

error_log($message, 0);
Xeoncross
  • 55,620
  • 80
  • 262
  • 364
  • 1
    error_log($message, 0) will use http://php.net/error-log directive, so you must set it right. If you use syslog there, then you should be OK: http://stackoverflow.com/questions/1163194/syslog-r-for-linux, but you should check syslog version on our system (safe on most systems). – XzKto Jun 22 '11 at 14:36

1 Answers1

19

You can find the source for the error_log implementation in ext/standard/basic_functions.c. You'll see that it pretty much just calls any defined logger. If you're concerned about some kind of data munging by error_log itself due to multiple concurrent calls, no need to be. Or at least, no more concerned than most any other piece of PHP code. If your custom logger is writing to a file, you'll need to implement file locking yourself. Concurrent calls to error_log (across processes) is a pretty common scenario.

edit

You are almost certainly better off using the built in logging available via error_log.

The PHP flock implementation uses advisory locking, which makes it possible for other processes to simply ignore the lock and write. Additionally, within your own processes you will end up being IO bound as the process waits to acquire the lock. By using error_log, you can configure syslog logging. Syslog is asynchronous so you avoid the lock acquisition, and it's also backed (generally) by a kernel buffer which will allow any syslog daemon to write consecutive records without a problem.

Having implemented high throughput logging at a number of companies I would strongly recommend configuring either syslog or going with something like scribe. My 2c.

hakre
  • 193,403
  • 52
  • 435
  • 836
Blake Mathman
  • 2,699
  • 1
  • 23
  • 20
  • So, can I call error_log() from my handler or do I need to create another log file which I can lock and use that instead? If the default PHP handler just calls error_log() then I feel safe using that in my handler. – Xeoncross Jun 16 '11 at 17:46
  • 2
    The file based logger that can be specified via your php.ini (error_log = '/tmp/log.txt') will be safely written to even with concurrent calls. You can call error_log() in your handler. – Blake Mathman Jun 16 '11 at 17:52
  • 1
    From this bug: https://bugs.php.net/bug.php?id=40897, I can confirm `error_log` is safe now and it is even better - since no locking is needed. – Ryan Mar 20 '13 at 15:24