diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 9062cf6f5c3cf..9fb972ae1958e 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -27,6 +27,7 @@ #include "zend_extensions.h" #include "zend_closures.h" #include "zend_generators.h" +#include "zend_smart_str.h" #include "zend_builtin_functions_arginfo.h" /* }}} */ @@ -2150,6 +2151,164 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int } /* }}} */ +/* {{{ */ +#define TRACE_APPEND_KEY(key) do { \ + tmp = zend_hash_find(ht, key); \ + if (tmp) { \ + if (Z_TYPE_P(tmp) != IS_STRING) { \ + zend_error(E_WARNING, "Value for %s is not a string", \ + ZSTR_VAL(key)); \ + smart_str_appends(str, "[unknown]"); \ + } else { \ + smart_str_appends(str, Z_STRVAL_P(tmp)); \ + } \ + } \ + } while (0) + +static void _build_trace_args(zval *arg, smart_str *str) /* {{{ */ +{ + /* the trivial way would be to do + * convert_to_string_ex(arg); + * append it and kill the now tmp arg. + * but that could cause some E_NOTICE and also damn long lines. + */ + + ZVAL_DEREF(arg); + switch (Z_TYPE_P(arg)) { + case IS_NULL: + smart_str_appends(str, "NULL, "); + break; + case IS_STRING: + smart_str_appendc(str, '\''); + smart_str_append_escaped(str, Z_STRVAL_P(arg), MIN(Z_STRLEN_P(arg), 15)); + if (Z_STRLEN_P(arg) > 15) { + smart_str_appends(str, "...', "); + } else { + smart_str_appends(str, "', "); + } + break; + case IS_FALSE: + smart_str_appends(str, "false, "); + break; + case IS_TRUE: + smart_str_appends(str, "true, "); + break; + case IS_RESOURCE: + smart_str_appends(str, "Resource id #"); + smart_str_append_long(str, Z_RES_HANDLE_P(arg)); + smart_str_appends(str, ", "); + break; + case IS_LONG: + smart_str_append_long(str, Z_LVAL_P(arg)); + smart_str_appends(str, ", "); + break; + case IS_DOUBLE: { + smart_str_append_printf(str, "%.*G", (int) EG(precision), Z_DVAL_P(arg)); + smart_str_appends(str, ", "); + break; + } + case IS_ARRAY: + smart_str_appends(str, "Array, "); + break; + case IS_OBJECT: { + zend_string *class_name = Z_OBJ_HANDLER_P(arg, get_class_name)(Z_OBJ_P(arg)); + smart_str_appends(str, "Object("); + smart_str_appends(str, ZSTR_VAL(class_name)); + smart_str_appends(str, "), "); + zend_string_release_ex(class_name, 0); + break; + } + } +} + +static void _build_trace_string(smart_str *str, HashTable *ht, uint32_t num) +{ + zval *file, *tmp; + + smart_str_appendc(str, '#'); + smart_str_append_long(str, num); + smart_str_appendc(str, ' '); + + file = zend_hash_find_ex(ht, ZSTR_KNOWN(ZEND_STR_FILE), 1); + if (file) { + if (Z_TYPE_P(file) != IS_STRING) { + zend_error(E_WARNING, "Function name is not a string"); + smart_str_appends(str, "[unknown function]"); + } else{ + zend_long line; + tmp = zend_hash_find_ex(ht, ZSTR_KNOWN(ZEND_STR_LINE), 1); + if (tmp) { + if (Z_TYPE_P(tmp) == IS_LONG) { + line = Z_LVAL_P(tmp); + } else { + zend_error(E_WARNING, "Line is not an int"); + line = 0; + } + } else { + line = 0; + } + smart_str_append(str, Z_STR_P(file)); + smart_str_appendc(str, '('); + smart_str_append_long(str, line); + smart_str_appends(str, "): "); + } + } else { + smart_str_appends(str, "[internal function]: "); + } + TRACE_APPEND_KEY(ZSTR_KNOWN(ZEND_STR_CLASS)); + TRACE_APPEND_KEY(ZSTR_KNOWN(ZEND_STR_TYPE)); + TRACE_APPEND_KEY(ZSTR_KNOWN(ZEND_STR_FUNCTION)); + smart_str_appendc(str, '('); + tmp = zend_hash_find_ex(ht, ZSTR_KNOWN(ZEND_STR_ARGS), 1); + if (tmp) { + if (Z_TYPE_P(tmp) == IS_ARRAY) { + size_t last_len = ZSTR_LEN(str->s); + zval *arg; + + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(tmp), arg) { + _build_trace_args(arg, str); + } ZEND_HASH_FOREACH_END(); + + if (last_len != ZSTR_LEN(str->s)) { + ZSTR_LEN(str->s) -= 2; /* remove last ', ' */ + } + } else { + zend_error(E_WARNING, "args element is not an array"); + } + } + smart_str_appends(str, ")\n"); +} +/* }}} */ + +/* {{{ */ +ZEND_API zend_string *zend_build_backtrace_string(zval *trace) +{ + zval *frame; + zend_ulong index; + smart_str str = {0}; + uint32_t num = 0; + + if (Z_TYPE_P(trace) != IS_ARRAY) { + zend_type_error("Trace is not an array"); + return NULL; + } + ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(trace), index, frame) { + if (Z_TYPE_P(frame) != IS_ARRAY) { + zend_error(E_WARNING, "Expected array for frame " ZEND_ULONG_FMT, index); + continue; + } + + _build_trace_string(&str, Z_ARRVAL_P(frame), num++); + } ZEND_HASH_FOREACH_END(); + + smart_str_appendc(&str, '#'); + smart_str_append_long(&str, num); + smart_str_appends(&str, " {main}"); + smart_str_0(&str); + + return str.s; +} + /* {{{ proto array debug_backtrace([int options[, int limit]]) Return backtrace as array */ ZEND_FUNCTION(debug_backtrace) diff --git a/Zend/zend_builtin_functions.h b/Zend/zend_builtin_functions.h index cfc347ed41ffc..0824c1e8a29ae 100644 --- a/Zend/zend_builtin_functions.h +++ b/Zend/zend_builtin_functions.h @@ -24,6 +24,7 @@ int zend_startup_builtin_functions(void); BEGIN_EXTERN_C() ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int options, int limit); +ZEND_API zend_string *zend_build_backtrace_string(zval *trace); END_EXTERN_C() #endif /* ZEND_BUILTIN_FUNCTIONS_H */ diff --git a/Zend/zend_errors.h b/Zend/zend_errors.h index dd7539523dbf2..3dbfb06cff6fd 100644 --- a/Zend/zend_errors.h +++ b/Zend/zend_errors.h @@ -39,6 +39,9 @@ /* Indicates that this usually fatal error should not result in a bailout */ #define E_DONT_BAIL (1<<15L) +/* Indicates that this error was caused by an uncaught exception */ +#define E_UNCAUGHT_EXCEPTION (1<<16L) + #define E_ALL (E_ERROR | E_WARNING | E_PARSE | E_NOTICE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE | E_RECOVERABLE_ERROR | E_DEPRECATED | E_USER_DEPRECATED | E_STRICT) #define E_CORE (E_CORE_ERROR | E_CORE_WARNING) diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index a2bdbdad746fb..d4e74ccc548ce 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -452,145 +452,14 @@ ZEND_METHOD(ErrorException, getSeverity) } /* }}} */ -#define TRACE_APPEND_KEY(key) do { \ - tmp = zend_hash_find(ht, key); \ - if (tmp) { \ - if (Z_TYPE_P(tmp) != IS_STRING) { \ - zend_error(E_WARNING, "Value for %s is not a string", \ - ZSTR_VAL(key)); \ - smart_str_appends(str, "[unknown]"); \ - } else { \ - smart_str_appends(str, Z_STRVAL_P(tmp)); \ - } \ - } \ - } while (0) - -static void _build_trace_args(zval *arg, smart_str *str) /* {{{ */ -{ - /* the trivial way would be to do - * convert_to_string_ex(arg); - * append it and kill the now tmp arg. - * but that could cause some E_NOTICE and also damn long lines. - */ - - ZVAL_DEREF(arg); - switch (Z_TYPE_P(arg)) { - case IS_NULL: - smart_str_appends(str, "NULL, "); - break; - case IS_STRING: - smart_str_appendc(str, '\''); - smart_str_append_escaped(str, Z_STRVAL_P(arg), MIN(Z_STRLEN_P(arg), 15)); - if (Z_STRLEN_P(arg) > 15) { - smart_str_appends(str, "...', "); - } else { - smart_str_appends(str, "', "); - } - break; - case IS_FALSE: - smart_str_appends(str, "false, "); - break; - case IS_TRUE: - smart_str_appends(str, "true, "); - break; - case IS_RESOURCE: - smart_str_appends(str, "Resource id #"); - smart_str_append_long(str, Z_RES_HANDLE_P(arg)); - smart_str_appends(str, ", "); - break; - case IS_LONG: - smart_str_append_long(str, Z_LVAL_P(arg)); - smart_str_appends(str, ", "); - break; - case IS_DOUBLE: { - smart_str_append_printf(str, "%.*G", (int) EG(precision), Z_DVAL_P(arg)); - smart_str_appends(str, ", "); - break; - } - case IS_ARRAY: - smart_str_appends(str, "Array, "); - break; - case IS_OBJECT: { - zend_string *class_name = Z_OBJ_HANDLER_P(arg, get_class_name)(Z_OBJ_P(arg)); - smart_str_appends(str, "Object("); - smart_str_appends(str, ZSTR_VAL(class_name)); - smart_str_appends(str, "), "); - zend_string_release_ex(class_name, 0); - break; - } - } -} -/* }}} */ - -static void _build_trace_string(smart_str *str, HashTable *ht, uint32_t num) /* {{{ */ -{ - zval *file, *tmp; - - smart_str_appendc(str, '#'); - smart_str_append_long(str, num); - smart_str_appendc(str, ' '); - - file = zend_hash_find_ex(ht, ZSTR_KNOWN(ZEND_STR_FILE), 1); - if (file) { - if (Z_TYPE_P(file) != IS_STRING) { - zend_error(E_WARNING, "Function name is not a string"); - smart_str_appends(str, "[unknown function]"); - } else{ - zend_long line; - tmp = zend_hash_find_ex(ht, ZSTR_KNOWN(ZEND_STR_LINE), 1); - if (tmp) { - if (Z_TYPE_P(tmp) == IS_LONG) { - line = Z_LVAL_P(tmp); - } else { - zend_error(E_WARNING, "Line is not an int"); - line = 0; - } - } else { - line = 0; - } - smart_str_append(str, Z_STR_P(file)); - smart_str_appendc(str, '('); - smart_str_append_long(str, line); - smart_str_appends(str, "): "); - } - } else { - smart_str_appends(str, "[internal function]: "); - } - TRACE_APPEND_KEY(ZSTR_KNOWN(ZEND_STR_CLASS)); - TRACE_APPEND_KEY(ZSTR_KNOWN(ZEND_STR_TYPE)); - TRACE_APPEND_KEY(ZSTR_KNOWN(ZEND_STR_FUNCTION)); - smart_str_appendc(str, '('); - tmp = zend_hash_find_ex(ht, ZSTR_KNOWN(ZEND_STR_ARGS), 1); - if (tmp) { - if (Z_TYPE_P(tmp) == IS_ARRAY) { - size_t last_len = ZSTR_LEN(str->s); - zval *arg; - - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(tmp), arg) { - _build_trace_args(arg, str); - } ZEND_HASH_FOREACH_END(); - - if (last_len != ZSTR_LEN(str->s)) { - ZSTR_LEN(str->s) -= 2; /* remove last ', ' */ - } - } else { - zend_error(E_WARNING, "args element is not an array"); - } - } - smart_str_appends(str, ")\n"); -} -/* }}} */ - /* {{{ proto string Exception|Error::getTraceAsString() Obtain the backtrace for the exception as a string (instead of an array) */ ZEND_METHOD(Exception, getTraceAsString) { - zval *trace, *frame, rv; - zend_ulong index; + zval *trace, rv; zval *object; zend_class_entry *base_ce; - smart_str str = {0}; - uint32_t num = 0; + zend_string *str; ZEND_PARSE_PARAMETERS_NONE(); @@ -604,21 +473,12 @@ ZEND_METHOD(Exception, getTraceAsString) /* Type should be guaranteed by property type. */ ZEND_ASSERT(Z_TYPE_P(trace) == IS_ARRAY); - ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(trace), index, frame) { - if (Z_TYPE_P(frame) != IS_ARRAY) { - zend_error(E_WARNING, "Expected array for frame " ZEND_ULONG_FMT, index); - continue; - } - - _build_trace_string(&str, Z_ARRVAL_P(frame), num++); - } ZEND_HASH_FOREACH_END(); - - smart_str_appendc(&str, '#'); - smart_str_append_long(&str, num); - smart_str_appends(&str, " {main}"); - smart_str_0(&str); + str = zend_build_backtrace_string(trace); + if (!str) { + RETURN_THROWS(); + } - RETURN_NEW_STR(str.s); + RETURN_NEW_STR(str); } /* }}} */ @@ -902,6 +762,8 @@ ZEND_API ZEND_COLD void zend_exception_error(zend_object *ex, int severity) /* { zval exception, rv; zend_class_entry *ce_exception; + severity |= E_UNCAUGHT_EXCEPTION; + ZVAL_OBJ(&exception, ex); ce_exception = ex->ce; EG(exception) = NULL; @@ -941,7 +803,7 @@ ZEND_API ZEND_COLD void zend_exception_error(zend_object *ex, int severity) /* { line = zval_get_long(GET_PROPERTY_SILENT(&zv, ZEND_STR_LINE)); } - zend_error_va(E_WARNING, (file && ZSTR_LEN(file) > 0) ? ZSTR_VAL(file) : NULL, line, + zend_error_va(E_WARNING | E_UNCAUGHT_EXCEPTION, (file && ZSTR_LEN(file) > 0) ? ZSTR_VAL(file) : NULL, line, "Uncaught %s in exception handling during call to %s::__tostring()", ZSTR_VAL(Z_OBJCE(zv)->name), ZSTR_VAL(ce_exception->name)); diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 7e0f4e3da7898..7e15c2158b57d 100755 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -1536,6 +1536,9 @@ PHP_FUNCTION(error_get_last) add_assoc_string_ex(return_value, "message", sizeof("message")-1, PG(last_error_message)); add_assoc_string_ex(return_value, "file", sizeof("file")-1, PG(last_error_file)?PG(last_error_file):"-"); add_assoc_long_ex(return_value, "line", sizeof("line")-1, PG(last_error_lineno)); + if (PG(last_error_backtrace)) { + add_assoc_string_ex(return_value, "backtrace", sizeof("backtrace")-1, PG(last_error_backtrace)); + } } } /* }}} */ @@ -1557,6 +1560,11 @@ PHP_FUNCTION(error_clear_last) free(PG(last_error_file)); PG(last_error_file) = NULL; } + + if (PG(last_error_backtrace)) { + free(PG(last_error_backtrace)); + PG(last_error_backtrace) = NULL; + } } } /* }}} */ diff --git a/main/main.c b/main/main.c index 6143718d05d42..3e59381abcea0 100644 --- a/main/main.c +++ b/main/main.c @@ -70,6 +70,7 @@ #include "zend_execute.h" #include "zend_highlight.h" #include "zend_extensions.h" +#include "zend_builtin_functions.h" #include "zend_ini.h" #include "zend_dtrace.h" @@ -486,6 +487,16 @@ static PHP_INI_MH(OnUpdateDisplayErrors) } /* }}} */ +/* {{{ PHP_INI_MH + */ +static PHP_INI_MH(OnUpdateErrorBacktraces) +{ + PG(error_backtraces) = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); + + return SUCCESS; +} +/* }}} */ + /* {{{ PHP_INI_DISP */ static PHP_INI_DISP(display_errors_mode) @@ -703,6 +714,7 @@ PHP_INI_BEGIN() STD_PHP_INI_ENTRY_EX("display_errors", "1", PHP_INI_ALL, OnUpdateDisplayErrors, display_errors, php_core_globals, core_globals, display_errors_mode) STD_PHP_INI_BOOLEAN("display_startup_errors", "1", PHP_INI_ALL, OnUpdateBool, display_startup_errors, php_core_globals, core_globals) + STD_PHP_INI_ENTRY("error_backtraces", "0", PHP_INI_ALL, OnUpdateErrorBacktraces, error_backtraces, php_core_globals, core_globals) STD_PHP_INI_BOOLEAN("enable_dl", "1", PHP_INI_SYSTEM, OnUpdateBool, enable_dl, php_core_globals, core_globals) STD_PHP_INI_BOOLEAN("expose_php", "1", PHP_INI_SYSTEM, OnUpdateBool, expose_php, php_core_globals, core_globals) STD_PHP_INI_ENTRY("docref_root", "", PHP_INI_ALL, OnUpdateString, docref_root, php_core_globals, core_globals) @@ -1188,6 +1200,30 @@ PHPAPI void php_html_puts(const char *str, size_t size) } /* }}} */ +/* {{{ */ +static ZEND_COLD char *php_backtrace_string() +{ + zval trace; + char *result = NULL; + /* In config, no limit is -1 while for zend_fetch_debug_backtrace(), + * no limit is 0. */ + int limit = PG(error_backtraces) > 0 ? PG(error_backtraces) : 0; + + zend_fetch_debug_backtrace(&trace, 0, 0, limit); + + if (Z_TYPE(trace) == IS_ARRAY) { + zend_string *str = zend_build_backtrace_string(&trace); + if (str) { + result = strdup(ZSTR_VAL(str)); + zend_string_efree(str); + } + } + zval_ptr_dtor(&trace); + + return result; +} +/* }}} */ + /* {{{ php_error_cb extended error handling function */ static ZEND_COLD void php_error_cb(int orig_type, const char *error_filename, const uint32_t error_lineno, const char *format, va_list args) @@ -1195,6 +1231,7 @@ static ZEND_COLD void php_error_cb(int orig_type, const char *error_filename, co char *buffer; int buffer_len, display; int type = orig_type & E_ALL; + char *backtrace = NULL; buffer_len = (int)vspprintf(&buffer, PG(log_errors_max_len), format, args); @@ -1260,10 +1297,29 @@ static ZEND_COLD void php_error_cb(int orig_type, const char *error_filename, co if (!error_filename) { error_filename = "Unknown"; } + if (PG(last_error_backtrace)) { + char *s = PG(last_error_backtrace); + PG(last_error_backtrace) = NULL; + free(s); + } PG(last_error_type) = type; PG(last_error_message) = strdup(buffer); PG(last_error_file) = strdup(error_filename); PG(last_error_lineno) = error_lineno; + + /* Don't report backtraces for uncaught exceptions. They already have this information, and here we only have information from + * the outermost scope. */ + if (PG(error_backtraces) && !(orig_type & E_UNCAUGHT_EXCEPTION)) { + char *bt = php_backtrace_string(); + if (bt) { + if (bt[0]) { + PG(last_error_backtrace) = bt; + spprintf(&backtrace, 0, "\n%s", bt); + } else { + free(bt); + } + } + } } /* display/log the error if necessary */ @@ -1321,7 +1377,7 @@ static ZEND_COLD void php_error_cb(int orig_type, const char *error_filename, co syslog(LOG_ALERT, "PHP %s: %s (%s)", error_type_str, buffer, GetCommandLine()); } #endif - spprintf(&log_buffer, 0, "PHP %s: %s in %s on line %" PRIu32, error_type_str, buffer, error_filename, error_lineno); + spprintf(&log_buffer, 0, "PHP %s: %s in %s on line %" PRIu32 "%s", error_type_str, buffer, error_filename, error_lineno, STR_PRINT(backtrace)); php_log_err_with_severity(log_buffer, syslog_type_int); efree(log_buffer); } @@ -1346,12 +1402,12 @@ static ZEND_COLD void php_error_cb(int orig_type, const char *error_filename, co if ((!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "cgi") || !strcmp(sapi_module.name, "phpdbg")) && PG(display_errors) == PHP_DISPLAY_ERRORS_STDERR ) { - fprintf(stderr, "%s: %s in %s on line %" PRIu32 "\n", error_type_str, buffer, error_filename, error_lineno); + fprintf(stderr, "%s: %s in %s on line %" PRIu32 "%s\n", error_type_str, buffer, error_filename, error_lineno, STR_PRINT(backtrace)); #ifdef PHP_WIN32 fflush(stderr); #endif } else { - php_printf("%s\n%s: %s in %s on line %" PRIu32 "\n%s", STR_PRINT(prepend_string), error_type_str, buffer, error_filename, error_lineno, STR_PRINT(append_string)); + php_printf("%s\n%s: %s in %s on line %" PRIu32 "%s\n%s", STR_PRINT(prepend_string), error_type_str, buffer, error_filename, error_lineno, STR_PRINT(backtrace), STR_PRINT(append_string)); } } } @@ -1371,7 +1427,7 @@ static ZEND_COLD void php_error_cb(int orig_type, const char *error_filename, co trigger_break=0; break; } - zend_output_debug_string(trigger_break, "%s(%" PRIu32 ") : %s - %s", error_filename, error_lineno, error_type_str, buffer); + zend_output_debug_string(trigger_break, "%s(%" PRIu32 ") : %s - %s%s", error_filename, error_lineno, error_type_str, buffer, backtrace); } #endif } @@ -1406,6 +1462,9 @@ static ZEND_COLD void php_error_cb(int orig_type, const char *error_filename, co /* restore memory limit */ zend_set_memory_limit(PG(memory_limit)); efree(buffer); + if (backtrace) { + efree(backtrace); + } zend_objects_store_mark_destructed(&EG(objects_store)); zend_bailout(); return; @@ -1415,6 +1474,9 @@ static ZEND_COLD void php_error_cb(int orig_type, const char *error_filename, co } efree(buffer); + if (backtrace) { + efree(backtrace); + } } /* }}} */ @@ -1725,6 +1787,7 @@ static void sigchld_handler(int apar) /* }}} */ #endif + /* {{{ php_request_startup */ int php_request_startup(void) diff --git a/main/php_globals.h b/main/php_globals.h index e5709ddc67444..6978d47fe0346 100644 --- a/main/php_globals.h +++ b/main/php_globals.h @@ -67,6 +67,7 @@ struct _php_core_globals { zend_bool display_errors; zend_bool display_startup_errors; + zend_long error_backtraces; zend_bool log_errors; zend_long log_errors_max_len; zend_bool ignore_repeated_errors; @@ -136,6 +137,7 @@ struct _php_core_globals { char *last_error_message; char *last_error_file; int last_error_lineno; + char *last_error_backtrace; char *php_sys_temp_dir; diff --git a/php.ini-development b/php.ini-development index 4acfa89a197c6..ed050d8ee74c1 100644 --- a/php.ini-development +++ b/php.ini-development @@ -113,6 +113,11 @@ ; Development Value: On ; Production Value: On +; error_backtraces +; Default Value: 0 +; Development Value: 100 +; Production Value: 0 + ; max_input_time ; Default Value: -1 (Unlimited) ; Development Value: 60 (60 seconds) @@ -503,6 +508,11 @@ log_errors = On ; http://php.net/log-errors-max-len log_errors_max_len = 1024 +; Maximum number of stack frames to report for PHP errors. +; 0 for no backtraces, -1 for no limit. +; http://php.net/debug-backtraces +debug_backtraces = 100 + ; Do not log repeated messages. Repeated errors must occur in same file on same ; line unless ignore_repeated_source is set true. ; http://php.net/ignore-repeated-errors diff --git a/php.ini-production b/php.ini-production index 2fdcdc0e5d3d2..48070689cd93b 100644 --- a/php.ini-production +++ b/php.ini-production @@ -113,6 +113,11 @@ ; Development Value: On ; Production Value: On +; error_backtraces +; Default Value: 0 +; Development Value: 100 +; Production Value: 0 + ; max_input_time ; Default Value: -1 (Unlimited) ; Development Value: 60 (60 seconds) @@ -505,6 +510,11 @@ log_errors = On ; http://php.net/log-errors-max-len log_errors_max_len = 1024 +; Maximum number of stack frames to report for PHP errors. +; 0 for no backtraces, -1 for no limit. +; http://php.net/debug-backtraces +debug_backtraces = 0 + ; Do not log repeated messages. Repeated errors must occur in same file on same ; line unless ignore_repeated_source is set true. ; http://php.net/ignore-repeated-errors