Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions Zend/zend_execute.c
Original file line number Diff line number Diff line change
Expand Up @@ -2106,22 +2106,17 @@ void zend_free_compiled_variables(zend_execute_data *execute_data) /* {{{ */
}
/* }}} */

#ifdef ZEND_WIN32
static zend_never_inline ZEND_COLD ZEND_NORETURN void ZEND_FASTCALL zend_interrupt(void) /* {{{ */
{
zend_timeout(0);
}
/* }}} */

# define ZEND_VM_INTERRUPT_CHECK() do { \
#define ZEND_VM_INTERRUPT_CHECK() do { \
if (UNEXPECTED(EG(timed_out))) { \
zend_interrupt(); \
} \
} while (0)
#else
# define ZEND_VM_INTERRUPT_CHECK() do { \
} while (0)
#endif

/*
* Stack Frame Layout (the whole stack frame is allocated at once)
Expand Down
87 changes: 74 additions & 13 deletions Zend/zend_execute_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

ZEND_API void (*zend_execute_ex)(zend_execute_data *execute_data);
ZEND_API void (*zend_execute_internal)(zend_execute_data *execute_data, zval *return_value);
Expand Down Expand Up @@ -169,9 +172,7 @@ void init_executor(void) /* {{{ */
zend_objects_store_init(&EG(objects_store), 1024);

EG(full_tables_cleanup) = 0;
#ifdef ZEND_WIN32
EG(timed_out) = 0;
#endif

EG(exception) = NULL;
EG(prev_exception) = NULL;
Expand Down Expand Up @@ -1183,8 +1184,47 @@ ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name,
}
/* }}} */

static void zend_set_timeout_ex(zend_long seconds, int reset_signals);

ZEND_API void zend_timeout(int dummy) /* {{{ */
{
EG(timed_out) = 0;
zend_set_timeout_ex(0, 1);
zend_error_noreturn(E_ERROR, "Maximum execution time of %pd second%s exceeded", EG(timeout_seconds), EG(timeout_seconds) == 1 ? "" : "s");
}
/* }}} */

#ifndef ZEND_WIN32
static void zend_timeout_handler(int dummy) /* {{{ */
{
#ifndef ZTS
if (EG(timed_out)) {
/* Die on hard timeout */
const char *error_filename = NULL;
uint error_lineno = 0;
char *log_buffer = NULL;

if (zend_is_compiling()) {
error_filename = ZSTR_VAL(zend_get_compiled_filename());
error_lineno = zend_get_compiled_lineno();
} else if (zend_is_executing()) {
error_filename = zend_get_executed_filename();
if (error_filename[0] == '[') { /* [no active file] */
error_filename = NULL;
error_lineno = 0;
} else {
error_lineno = zend_get_executed_lineno();
}
}
if (!error_filename) {
error_filename = "Unknown";
}

zend_spprintf(&log_buffer, 0, "\nFatal error: Maximum execution time of %pd+%pd seconds exceeded (terminated) in %s on line %d\n", EG(timeout_seconds), EG(hard_timeout), error_filename, error_lineno);
write(2, log_buffer, strlen(log_buffer));
_exit(1);
}
#endif

if (zend_on_timeout) {
#ifdef ZEND_SIGNALS
Expand All @@ -1199,9 +1239,17 @@ ZEND_API void zend_timeout(int dummy) /* {{{ */
zend_on_timeout(EG(timeout_seconds));
}

zend_error_noreturn(E_ERROR, "Maximum execution time of %pd second%s exceeded", EG(timeout_seconds), EG(timeout_seconds) == 1 ? "" : "s");
EG(timed_out) = 1;

#ifndef ZTS
if (EG(hard_timeout) > 0) {
/* Set hard timeout */
zend_set_timeout_ex(EG(hard_timeout), 1);
}
#endif
}
/* }}} */
#endif

#ifdef ZEND_WIN32
VOID CALLBACK tq_timer_cb(PVOID arg, BOOLEAN timed_out)
Expand All @@ -1224,11 +1272,9 @@ VOID CALLBACK tq_timer_cb(PVOID arg, BOOLEAN timed_out)
#define SIGPROF 27
#endif

void zend_set_timeout(zend_long seconds, int reset_signals) /* {{{ */
static void zend_set_timeout_ex(zend_long seconds, int reset_signals) /* {{{ */
{

EG(timeout_seconds) = seconds;

#ifdef ZEND_WIN32
if(!seconds) {
return;
Expand All @@ -1239,7 +1285,6 @@ void zend_set_timeout(zend_long seconds, int reset_signals) /* {{{ */
delete and recreate. */
if (NULL != tq_timer) {
if (!DeleteTimerQueueTimer(NULL, tq_timer, NULL)) {
EG(timed_out) = 0;
tq_timer = NULL;
zend_error_noreturn(E_ERROR, "Could not delete queued timer");
return;
Expand All @@ -1249,12 +1294,10 @@ void zend_set_timeout(zend_long seconds, int reset_signals) /* {{{ */

/* XXX passing NULL means the default timer queue provided by the system is used */
if (!CreateTimerQueueTimer(&tq_timer, NULL, (WAITORTIMERCALLBACK)tq_timer_cb, (VOID*)&EG(timed_out), seconds*1000, 0, WT_EXECUTEONLYONCE)) {
EG(timed_out) = 0;
tq_timer = NULL;
zend_error_noreturn(E_ERROR, "Could not queue new timer");
return;
}
EG(timed_out) = 0;
#else
# ifdef HAVE_SETITIMER
{
Expand All @@ -1277,22 +1320,39 @@ void zend_set_timeout(zend_long seconds, int reset_signals) /* {{{ */

if (reset_signals) {
# ifdef ZEND_SIGNALS
zend_signal(signo, zend_timeout);
zend_signal(signo, zend_timeout_handler);
# else
sigset_t sigset;

signal(signo, zend_timeout);
# ifdef HAVE_SIGACTION
struct sigaction act;

act.sa_handler = zend_timeout_handler;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESETHAND | SA_NODEFER;
sigaction(signo, &act, NULL);
# else
signal(signo, zend_timeout_handler);
# endif /* HAVE_SIGACTION */
sigemptyset(&sigset);
sigaddset(&sigset, signo);
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
# endif
# endif /* ZEND_SIGNALS */
}
}
# endif /* HAVE_SETITIMER */
#endif
}
/* }}} */

void zend_set_timeout(zend_long seconds, int reset_signals) /* {{{ */
{

EG(timeout_seconds) = seconds;
zend_set_timeout_ex(seconds, reset_signals);
EG(timed_out) = 0;
}
/* }}} */

void zend_unset_timeout(void) /* {{{ */
{
#ifdef ZEND_WIN32
Expand Down Expand Up @@ -1320,6 +1380,7 @@ void zend_unset_timeout(void) /* {{{ */
#endif
}
# endif
EG(timed_out) = 0;
#endif
}
/* }}} */
Expand Down
4 changes: 3 additions & 1 deletion Zend/zend_globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,10 @@ struct _zend_executor_globals {
/* for extended information support */
zend_bool no_extensions;

#ifdef ZEND_WIN32
zend_bool timed_out;
zend_long hard_timeout;

#ifdef ZEND_WIN32
OSVERSIONINFOEX windows_version_info;
#endif

Expand Down
4 changes: 1 addition & 3 deletions main/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,7 @@ PHP_INI_BEGIN()

STD_PHP_INI_ENTRY("user_ini.filename", ".user.ini", PHP_INI_SYSTEM, OnUpdateString, user_ini_filename, php_core_globals, core_globals)
STD_PHP_INI_ENTRY("user_ini.cache_ttl", "300", PHP_INI_SYSTEM, OnUpdateLong, user_ini_cache_ttl, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("exit_on_timeout", "0", PHP_INI_ALL, OnUpdateBool, exit_on_timeout, php_core_globals, core_globals)
STD_PHP_INI_ENTRY("hard_timeout", "2", PHP_INI_SYSTEM, OnUpdateLong, hard_timeout, zend_executor_globals, executor_globals)
#ifdef PHP_WIN32
STD_PHP_INI_BOOLEAN("windows.show_crt_warning", "0", PHP_INI_ALL, OnUpdateBool, windows_show_crt_warning, php_core_globals, core_globals)
#endif
Expand Down Expand Up @@ -1505,8 +1505,6 @@ static ZEND_COLD void php_message_handler_for_zend(zend_long message, const void
void php_on_timeout(int seconds)
{
PG(connection_status) |= PHP_CONNECTION_TIMEOUT;
zend_set_timeout(EG(timeout_seconds), 1);
if(PG(exit_on_timeout)) sapi_terminate_process();
}

#if PHP_SIGCHILD
Expand Down
1 change: 0 additions & 1 deletion main/php_globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@ struct _php_core_globals {
char *disable_functions;
char *disable_classes;
zend_bool allow_url_include;
zend_bool exit_on_timeout;
#ifdef PHP_WIN32
zend_bool com_initialized;
#endif
Expand Down