Index: trunk/php/wmerrors/wmerrors.c |
— | — | @@ -17,6 +17,7 @@ |
18 | 18 | |
19 | 19 | void wmerrors_cb(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args); |
20 | 20 | static void wmerrors_show_message(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args TSRMLS_DC); |
| 21 | +void wmerrors_get_backtrace(smart_str *s); |
21 | 22 | |
22 | 23 | |
23 | 24 | ZEND_DECLARE_MODULE_GLOBALS(wmerrors) |
— | — | @@ -118,6 +119,7 @@ |
119 | 120 | |
120 | 121 | void wmerrors_cb(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) |
121 | 122 | { |
| 123 | + smart_str new_filename = {0}; |
122 | 124 | TSRMLS_FETCH(); |
123 | 125 | |
124 | 126 | /* Do not call the custom error handling if: |
— | — | @@ -153,14 +155,67 @@ |
154 | 156 | /* Log the error */ |
155 | 157 | wmerrors_log_error(type, error_filename, error_lineno, format, args TSRMLS_CC); |
156 | 158 | } |
| 159 | + |
| 160 | + /* Put a concise backtrace in the normal output */ |
| 161 | + /* TODO: Make configurable */ |
| 162 | + wmerrors_get_backtrace(&new_filename); |
| 163 | + smart_str_appendl(&new_filename, error_filename, strlen(error_filename)); |
| 164 | + smart_str_0(&new_filename); |
157 | 165 | |
158 | 166 | WMERRORS_G(recursion_guard) = 0; |
159 | 167 | zend_set_memory_limit(PG(memory_limit)); |
160 | 168 | |
161 | 169 | /* Pass through */ |
162 | | - old_error_cb(type, error_filename, error_lineno, format, args); |
| 170 | + old_error_cb(type, new_filename.c, error_lineno, format, args); |
| 171 | + smart_str_free(&new_filename); |
163 | 172 | } |
164 | 173 | |
| 174 | +/* Obtain a concisely formatted backtrace */ |
| 175 | +void wmerrors_get_backtrace(smart_str *s) { |
| 176 | + zval *trace, **entry, **file, **line, *line_copy; |
| 177 | + HashPosition pos; |
| 178 | + char *basename; |
| 179 | + size_t basename_len; |
| 180 | + int use_copy; |
| 181 | + |
| 182 | + TSRMLS_FETCH(); |
| 183 | + ALLOC_INIT_ZVAL(trace); |
| 184 | + zend_fetch_debug_backtrace(trace, 0, 0 TSRMLS_CC); |
| 185 | + |
| 186 | + if (!trace || Z_TYPE_P(trace) != IS_ARRAY) { |
| 187 | + /* Not supposed to happen */ |
| 188 | + return; |
| 189 | + } |
| 190 | + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(trace), &pos); |
| 191 | + while (zend_hash_get_current_data_ex(Z_ARRVAL_P(trace), (void **)&entry, &pos) == SUCCESS) { |
| 192 | + if (!entry || !*entry || Z_TYPE_PP(entry) != IS_ARRAY) { |
| 193 | + /* Not supposed to happen */ |
| 194 | + smart_str_appendl(s, "?!? ", sizeof("?!? ")); |
| 195 | + continue; |
| 196 | + } |
| 197 | + zend_hash_find(Z_ARRVAL_PP(entry), "file", sizeof("file"), (void **)&file); |
| 198 | + zend_hash_find(Z_ARRVAL_PP(entry), "line", sizeof("line"), (void **)&line); |
| 199 | + |
| 200 | + if(!file || !*file || Z_TYPE_PP(file) != IS_STRING || !line || !*line || Z_TYPE_PP(line) != IS_LONG) { |
| 201 | + /* Not supposed to happen */ |
| 202 | + smart_str_appendl(s, "?!?!? ", sizeof("?!?!? ")); |
| 203 | + continue; |
| 204 | + } |
| 205 | + php_basename(Z_STRVAL_PP(file), Z_STRLEN_PP(file), NULL, 0, &basename, &basename_len TSRMLS_CC); |
| 206 | + ALLOC_INIT_ZVAL(line_copy); |
| 207 | + zend_make_printable_zval(*line, line_copy, &use_copy); |
| 208 | + smart_str_appendl(s, basename, basename_len); |
| 209 | + smart_str_appendc(s, ':'); |
| 210 | + smart_str_appendl(s, Z_STRVAL_P((use_copy ? line_copy : *line)), Z_STRLEN_P((use_copy ? line_copy : *line))); |
| 211 | + smart_str_appendc(s, ' '); |
| 212 | + |
| 213 | + efree(basename); |
| 214 | + FREE_ZVAL(line_copy); |
| 215 | + zend_hash_move_forward_ex(Z_ARRVAL_P(trace), &pos); |
| 216 | + } |
| 217 | + FREE_ZVAL(trace); |
| 218 | +} |
| 219 | + |
165 | 220 | static php_stream * open_logging_file(const char* stream_name) { |
166 | 221 | php_stream * stream; |
167 | 222 | int err; char *errstr = NULL; |