https://www.mediawiki.org/wiki/Special:Code/MediaWiki/115649

Revision: 115649
Author:   tstarling
Date:     2012-08-09 12:02:51 +0000 (Thu, 09 Aug 2012)
Log Message:
-----------
* Added a log_line_prefix option to allow each line of the log to be prefixed 
with a specified string. This should allow it to be used with the main 
multiplexed udp2log instance, instead of requiring a separate log server.
* Don't abort in ZTS mode.
* Fixed incorrect smart_str_free() call, was freeing some other random variable.

Modified Paths:
--------------
    trunk/php/wmerrors/debian/changelog
    trunk/php/wmerrors/php_wmerrors.h
    trunk/php/wmerrors/wmerrors.c

Modified: trunk/php/wmerrors/debian/changelog
===================================================================
--- trunk/php/wmerrors/debian/changelog 2012-08-09 02:48:36 UTC (rev 115648)
+++ trunk/php/wmerrors/debian/changelog 2012-08-09 12:02:51 UTC (rev 115649)
@@ -1,3 +1,10 @@
+php5-wmerrors (1.1.5-1) precise-wikimedia; urgency=low
+
+  * Added log_line_prefix option
+  * Fixed deadlock due to calling timer_create() from a signal handler.
+
+ -- Tim Starling <tstarl...@wikimedia.org>  Thu, 09 Aug 2012 21:51:58 +1000
+
 php5-wmerrors (1.1.4-2) precise-wikimedia; urgency=low
 
   * Build for precise.

Modified: trunk/php/wmerrors/php_wmerrors.h
===================================================================
--- trunk/php/wmerrors/php_wmerrors.h   2012-08-09 02:48:36 UTC (rev 115648)
+++ trunk/php/wmerrors/php_wmerrors.h   2012-08-09 12:02:51 UTC (rev 115649)
@@ -32,15 +32,16 @@
 ZEND_BEGIN_MODULE_GLOBALS(wmerrors)
        char * message_file;
        char * log_file;
+       char * log_line_prefix;
        int recursion_guard;
        int enabled;
        int log_backtrace;
        int ignore_logging_errors;
        int backtrace_in_php_error_message;
        long timeout;
-       int alarm_set;
        void (*old_on_timeout)(int seconds TSRMLS_DC);
 #ifdef WMERRORS_USE_TIMER
+       int timer_created;
        struct sigaction old_rt_action;
        timer_t timer;
 #endif

Modified: trunk/php/wmerrors/wmerrors.c
===================================================================
--- trunk/php/wmerrors/wmerrors.c       2012-08-09 02:48:36 UTC (rev 115648)
+++ trunk/php/wmerrors/wmerrors.c       2012-08-09 12:02:51 UTC (rev 115649)
@@ -18,11 +18,12 @@
 static void wmerrors_cb(int type, const char *error_filename, const uint 
error_lineno, const char *format, va_list args);
 static void wmerrors_show_message(int type, const char *error_filename, const 
uint error_lineno, const char *format, va_list args TSRMLS_DC);
 static void wmerrors_get_concise_backtrace(smart_str *s TSRMLS_DC);
-static void wmerrors_write_full_backtrace(php_stream *logfile_stream);
-static void wmerrors_write_request_info(php_stream *logfile_stream TSRMLS_DC);
+static void wmerrors_write_full_backtrace(smart_str *s TSRMLS_DC);
+static void wmerrors_write_request_info(smart_str *s TSRMLS_DC);
 static void wmerrors_alarm_handler(int signo);
-static void wmerrors_install_alarm(TSRMLS_D);
-static void wmerrors_remove_alarm(TSRMLS_D);
+static void wmerrors_create_timer(TSRMLS_D);
+static void wmerrors_destroy_timer(TSRMLS_D);
+static void wmerrors_start_timer(TSRMLS_D);
 
 ZEND_DECLARE_MODULE_GLOBALS(wmerrors)
 
@@ -66,6 +67,7 @@
        STD_PHP_INI_ENTRY("wmerrors.message_file", "", PHP_INI_ALL, 
OnUpdateString, message_file, zend_wmerrors_globals, wmerrors_globals)
        STD_PHP_INI_ENTRY("wmerrors.log_file", "", PHP_INI_ALL, OnUpdateString, 
log_file, zend_wmerrors_globals, wmerrors_globals)
        STD_PHP_INI_BOOLEAN("wmerrors.log_backtrace", "0", PHP_INI_ALL, 
OnUpdateBool, log_backtrace, zend_wmerrors_globals, wmerrors_globals)
+       STD_PHP_INI_ENTRY("wmerrors.log_line_prefix", "", PHP_INI_ALL, 
OnUpdateString, log_line_prefix, zend_wmerrors_globals, wmerrors_globals)
        STD_PHP_INI_BOOLEAN("wmerrors.ignore_logging_errors", "0", PHP_INI_ALL, 
OnUpdateBool, ignore_logging_errors, zend_wmerrors_globals, wmerrors_globals)
        STD_PHP_INI_BOOLEAN("wmerrors.backtrace_in_php_error_message", "0", 
PHP_INI_ALL, OnUpdateBool, backtrace_in_php_error_message, 
zend_wmerrors_globals, wmerrors_globals)
        STD_PHP_INI_ENTRY("wmerrors.timeout", "10", PHP_INI_ALL, OnUpdateLong, 
timeout, zend_wmerrors_globals, wmerrors_globals)
@@ -78,6 +80,10 @@
        wmerrors_globals->message_file = NULL;
        wmerrors_globals->log_file = NULL;
        wmerrors_globals->log_backtrace = 0;
+       wmerrors_globals->log_line_prefix = NULL;
+#ifdef WMERRORS_USE_TIMER
+       wmerrors_globals->timer_created = 0;
+#endif
 }
 
 PHP_MINIT_FUNCTION(wmerrors)
@@ -102,7 +108,7 @@
 PHP_RINIT_FUNCTION(wmerrors)
 {
        WMERRORS_G(recursion_guard) = 0;
-       WMERRORS_G(alarm_set) = 0;
+       wmerrors_create_timer(TSRMLS_C);
        return SUCCESS;
 }
 
@@ -116,7 +122,7 @@
 int wmerrors_post_deactivate()
 {
        TSRMLS_FETCH();
-       wmerrors_remove_alarm(TSRMLS_C);
+       wmerrors_destroy_timer(TSRMLS_C);
        return SUCCESS;
 }
 
@@ -167,7 +173,7 @@
        zend_set_memory_limit((size_t)-1);
 
        if (WMERRORS_G(timeout)) {
-               wmerrors_install_alarm(TSRMLS_C);
+               wmerrors_start_timer(TSRMLS_C);
        }
 
        /* Do not show the html error to console */
@@ -191,19 +197,21 @@
        WMERRORS_G(recursion_guard) = 0;
        zend_set_memory_limit(PG(memory_limit));
 
+#ifndef ZTS
        if (PG(connection_status) & PHP_CONNECTION_TIMEOUT) {
                /* abort instead of deadlocking */
                const char abort_message[] = "wmerrors: doing precautionary 
abort() after request timeout\n";
                write(STDERR_FILENO, abort_message, sizeof(abort_message) - 1);
                abort();
        }
+#endif
 
        /* Pass through */
        old_error_cb(type, new_filename.c, error_lineno, format, args);
        
        /* Note: old_error_cb() may not return, in which case there will be no 
         * explicit free of new_filename */
-       smart_str_free(&old_error_cb);
+       smart_str_free(&new_filename);
 }
 
 /* Obtain a concisely formatted backtrace */
@@ -259,7 +267,7 @@
        FREE_ZVAL(trace);
 }
 
-static php_stream * wmerrors_open_log_file(const char* stream_name) {
+static php_stream * wmerrors_open_log_file(const char* stream_name TSRMLS_DC) {
        php_stream * stream;
        int err; char *errstr = NULL;
        struct timeval tv;
@@ -287,12 +295,14 @@
 }
 
 static void wmerrors_log_error(int type, const char *error_filename, const 
uint error_lineno, const char *format, va_list args TSRMLS_DC) {
-       char *tmp1;
-       int tmp1_len;
+       char *input_message, *first_line;
+       int input_message_len, first_line_len;
        char *error_time_str;
        va_list my_args;
        php_stream *logfile_stream;
        int old_error_reporting;
+       smart_str message = {NULL};
+       smart_str prefixed_message = {NULL};
        
        if ( !WMERRORS_G(enabled) ) {
                /* Redundant with the caller */
@@ -307,7 +317,7 @@
        /* Try opening the logging file */
        /* Set recursion_guard==2 whenever we're doing something to the log 
file */
        WMERRORS_G(recursion_guard) = 2;
-       logfile_stream = wmerrors_open_log_file( WMERRORS_G(log_file) );
+       logfile_stream = wmerrors_open_log_file(WMERRORS_G(log_file) TSRMLS_CC);
        WMERRORS_G(recursion_guard) = 1;
        if ( !logfile_stream ) {
                return;
@@ -315,7 +325,8 @@
        
        /* Don't destroy the caller's va_list */
        va_copy(my_args, args);
-       tmp1_len = vspprintf(&tmp1, 0, format, my_args);
+       /* Write the input message */
+       input_message_len = vspprintf(&input_message, 0, format, my_args);
        va_end(my_args);
        
        /* Get a date string (without warning messages) */
@@ -324,30 +335,59 @@
        error_time_str = php_format_date("d-M-Y H:i:s", 11, time(NULL), 1 
TSRMLS_CC);
        EG(error_reporting) = old_error_reporting;
 
-       /* Log the error */
-       php_stream_printf(logfile_stream TSRMLS_CC, "[%s] %s: %.*s at %s on 
line %u%s", 
-                       error_time_str, wmerrors_error_type_to_string(type), 
tmp1_len, tmp1, error_filename, 
+       /* Make the initial log line */
+       first_line_len = spprintf(&first_line, 0, "[%s] %s: %.*s at %s on line 
%u%s", 
+                       error_time_str, wmerrors_error_type_to_string(type), 
+                       input_message_len, input_message, error_filename, 
                        error_lineno, PHP_EOL);
+       smart_str_appendl(&message, first_line, first_line_len);
        efree(error_time_str);
-       efree(tmp1);
+       efree(input_message);
+       efree(first_line);
        
        /* Write the request info */
-       wmerrors_write_request_info(logfile_stream TSRMLS_CC);
+       wmerrors_write_request_info(&message TSRMLS_CC);
 
        /* Write a backtrace */
        if ( WMERRORS_G(log_backtrace) ) {
-               php_stream_printf(logfile_stream TSRMLS_CC, "Backtrace:%s", 
PHP_EOL);
-               wmerrors_write_full_backtrace(logfile_stream TSRMLS_CC);
+               smart_str_appends(&message, "Backtrace:");
+               smart_str_appends(&message, PHP_EOL);
+               wmerrors_write_full_backtrace(&message TSRMLS_CC);
        }
-       
-       php_stream_close( logfile_stream );
+
+       /* Add the log line prefix if requested */
+       if (message.c && WMERRORS_G(log_line_prefix) && 
WMERRORS_G(log_line_prefix)[0]) {
+               char * line_start = message.c;
+               char * message_end = message.c + message.len;
+               char * line_end;
+               while (line_start < message_end) {
+                       smart_str_appends(&prefixed_message, 
WMERRORS_G(log_line_prefix));
+                       line_end = memchr(line_start, '\n', message_end - 
line_start);
+                       if (!line_end) {
+                               line_end = message_end - 1;
+                       }
+                       smart_str_appendl(&prefixed_message, line_start, 
line_end - line_start + 1);
+                       line_start = line_end + 1;
+               }
+               smart_str_free(&message);
+       } else {
+               prefixed_message = message;
+       }
+
+       WMERRORS_G(recursion_guard) = 2;
+       if (prefixed_message.c) {
+               php_stream_write(logfile_stream, prefixed_message.c, 
prefixed_message.len);
+       }
+       php_stream_close(logfile_stream);
+       WMERRORS_G(recursion_guard) = 1;
+       smart_str_free(&prefixed_message);
 }
 
 
 /**
  * Write a backtrace to a stream
  */
-static void wmerrors_write_full_backtrace(php_stream *logfile_stream) {
+static void wmerrors_write_full_backtrace(smart_str * s TSRMLS_DC) {
        zval *trace = NULL;
        zval backtrace_fname;
        int status;
@@ -376,12 +416,10 @@
 
        /* Write it */
        convert_to_string(trace);
-       WMERRORS_G(recursion_guard) = 2;
        Z_STRVAL_P(trace) = erealloc( Z_STRVAL_P(trace), 
Z_STRLEN_P(trace)+sizeof(PHP_EOL) );
        memcpy(Z_STRVAL_P(trace) + Z_STRLEN_P(trace), PHP_EOL, sizeof(PHP_EOL));
        Z_STRLEN_P(trace) += sizeof(PHP_EOL) - 1; /* minus one for null */
-       php_stream_write(logfile_stream, Z_STRVAL_P(trace), Z_STRLEN_P(trace) 
TSRMLS_CC);
-       WMERRORS_G(recursion_guard) = 1;
+       smart_str_appendl(s, Z_STRVAL_P(trace), Z_STRLEN_P(trace));
 
        zval_ptr_dtor(&trace);
 }
@@ -389,59 +427,54 @@
 /**
  * Write the current URL to a stream
  */
-static void wmerrors_write_request_info(php_stream *logfile_stream TSRMLS_DC) {
+static void wmerrors_write_request_info(smart_str * s TSRMLS_DC) {
        HashTable * server_ht;
        zval **info;
-       smart_str s = {NULL};
        char *hostname;
 
        server_ht = Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]);
 
        /* Server */
        hostname = php_get_uname('n');
-       smart_str_appends(&s, "Server: ");
-       smart_str_appends(&s, hostname);
-       smart_str_appends(&s, PHP_EOL);
+       smart_str_appends(s, "Server: ");
+       smart_str_appends(s, hostname);
+       smart_str_appends(s, PHP_EOL);
        efree(hostname);
 
        /* Method */
        if (SG(request_info).request_method) {
-               smart_str_appends(&s, "Method: ");
-               smart_str_appends(&s, SG(request_info).request_method);
-               smart_str_appends(&s, PHP_EOL);
+               smart_str_appends(s, "Method: ");
+               smart_str_appends(s, SG(request_info).request_method);
+               smart_str_appends(s, PHP_EOL);
        }
 
        /* URL */
-       smart_str_appends(&s, "URL: ");
+       smart_str_appends(s, "URL: ");
        if (zend_hash_find(server_ht, "HTTPS", sizeof("HTTPS"), 
(void**)(&info)) == SUCCESS) {
-               smart_str_appends(&s, "https://";);
+               smart_str_appends(s, "https://";);
        } else {
-               smart_str_appends(&s, "http://";);
+               smart_str_appends(s, "http://";);
        }
        if (zend_hash_find(server_ht, "HTTP_HOST", sizeof("HTTP_HOST"), 
(void**)(&info)) == SUCCESS) {
-               smart_str_appendl(&s, Z_STRVAL_PP(info), Z_STRLEN_PP(info));
+               smart_str_appendl(s, Z_STRVAL_PP(info), Z_STRLEN_PP(info));
        } else {
-               smart_str_appends(&s, "[unknown-host]");
+               smart_str_appends(s, "[unknown-host]");
        }
        if (SG(request_info).request_uri) {
-               smart_str_appends(&s, SG(request_info).request_uri);
+               smart_str_appends(s, SG(request_info).request_uri);
        }
        if (SG(request_info).query_string) {
-               smart_str_appendc(&s, '?');
-               smart_str_appends(&s, SG(request_info).query_string);
+               smart_str_appendc(s, '?');
+               smart_str_appends(s, SG(request_info).query_string);
        }
-       smart_str_appends(&s, PHP_EOL);
+       smart_str_appends(s, PHP_EOL);
 
        /* Cookie */
        if (SG(request_info).cookie_data) {
-               smart_str_appends(&s, "Cookie: ");
-               smart_str_appends(&s, SG(request_info).cookie_data);
-               smart_str_appends(&s, PHP_EOL);
+               smart_str_appends(s, "Cookie: ");
+               smart_str_appends(s, SG(request_info).cookie_data);
+               smart_str_appends(s, PHP_EOL);
        }
-       if (s.c) {
-               php_stream_write(logfile_stream, s.c, s.len TSRMLS_CC);
-       }
-       smart_str_free(&s);
 }
 
 static void wmerrors_show_message(int type, const char *error_filename, const 
uint error_lineno, const char *format, va_list args TSRMLS_DC)
@@ -579,13 +612,15 @@
        abort();
 }
 
-static void wmerrors_install_alarm(TSRMLS_D) {
+/**
+ * The timer has to be created in advance, since timer_create() calls malloc().
+ */
+static void wmerrors_create_timer(TSRMLS_D) {
 #ifdef WMERRORS_USE_TIMER
        struct sigaction sa;
        struct sigevent evp;
-       struct itimerspec its;
 
-       memset(&sa, sizeof(sa), 0);
+       memset(&sa, 0, sizeof(sa));
        sa.sa_handler = wmerrors_alarm_handler;
        sigaction(SIGRTMIN+3, &sa, &WMERRORS_G(old_rt_action));
 
@@ -595,21 +630,29 @@
                perror("timer_create");
                abort();
        }
+       WMERRORS_G(timer_created) = 1;
+#endif
+}
 
+static void wmerrors_start_timer(TSRMLS_D) {
+#ifdef WMERRORS_USE_TIMER
+       if (!WMERRORS_G(timer_created)) {
+               return;
+       }
+       struct itimerspec its;
        its.it_value.tv_sec = WMERRORS_G(timeout);
        its.it_value.tv_nsec = 0;
        its.it_interval.tv_sec = its.it_interval.tv_nsec = 0;
        timer_settime(WMERRORS_G(timer), 0, &its, NULL);
-       WMERRORS_G(alarm_set) = 1;
 #endif
 }
 
-static void wmerrors_remove_alarm(TSRMLS_D) {
+static void wmerrors_destroy_timer(TSRMLS_D) {
 #ifdef WMERRORS_USE_TIMER
-       if (WMERRORS_G(alarm_set)) {
+       if (WMERRORS_G(timer)) {
                timer_delete(WMERRORS_G(timer));
+               WMERRORS_G(timer_created) = 0;
                sigaction(SIGRTMIN+3, &WMERRORS_G(old_rt_action), NULL);
-               WMERRORS_G(alarm_set) = 0;
        }
 #endif
 }


_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to