summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/zend.c3
-rw-r--r--Zend/zend_execute.h7
-rw-r--r--Zend/zend_execute_API.c159
3 files changed, 41 insertions, 128 deletions
diff --git a/Zend/zend.c b/Zend/zend.c
index f429b2d2a4..89977e7734 100644
--- a/Zend/zend.c
+++ b/Zend/zend.c
@@ -728,9 +728,6 @@ void zend_shutdown(TSRMLS_D) /* {{{ */
#ifdef ZEND_SIGNALS
zend_signal_shutdown(TSRMLS_C);
#endif
-#ifdef ZEND_WIN32
- zend_shutdown_timeout_thread();
-#endif
zend_destroy_rsrc_list(&EG(persistent_list) TSRMLS_CC);
if (EG(active))
{
diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h
index 3eab9662db..a410f47edf 100644
--- a/Zend/zend_execute.h
+++ b/Zend/zend_execute.h
@@ -234,13 +234,6 @@ void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC);
ZEND_API void zend_fetch_dimension_by_zval(zval *result, zval *container, zval *dim TSRMLS_DC);
-#ifdef ZEND_WIN32
-void zend_init_timeout_thread(void);
-void zend_shutdown_timeout_thread(void);
-#define WM_REGISTER_ZEND_TIMEOUT (WM_USER+1)
-#define WM_UNREGISTER_ZEND_TIMEOUT (WM_USER+2)
-#endif
-
ZEND_API zval* zend_get_compiled_variable_value(const zend_execute_data *execute_data_ptr, uint32_t var);
#define ZEND_USER_OPCODE_CONTINUE 0 /* execute next opcode */
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 2496f59136..760747affa 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -46,13 +46,10 @@ ZEND_API const zend_fcall_info empty_fcall_info = { 0, NULL, {{0}, {{0}}, {0}},
ZEND_API const zend_fcall_info_cache empty_fcall_info_cache = { 0, NULL, NULL, NULL, NULL };
#ifdef ZEND_WIN32
-#include <process.h>
-static WNDCLASS wc;
-static HWND timeout_window;
-static HANDLE timeout_thread_event;
-static HANDLE timeout_thread_handle;
-static unsigned timeout_thread_id;
-static volatile long timeout_thread_initialized=0;
+#ifdef ZTS
+__declspec(thread)
+#endif
+HANDLE tq_timer = NULL;
#endif
#if 0&&ZEND_DEBUG
@@ -1157,115 +1154,19 @@ ZEND_API void zend_timeout(int dummy) /* {{{ */
/* }}} */
#ifdef ZEND_WIN32
-static LRESULT CALLBACK zend_timeout_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) /* {{{ */
-{
-#ifdef ZTS
- THREAD_T thread_id = (THREAD_T)wParam;
-#endif
-
- switch (message) {
- case WM_DESTROY:
- PostQuitMessage(0);
- break;
- case WM_REGISTER_ZEND_TIMEOUT:
- /* wParam is the thread id pointer, lParam is the timeout amount in seconds */
- if (lParam == 0) {
- KillTimer(timeout_window, wParam);
- } else {
-#ifdef ZTS
- void ***tsrm_ls;
-#endif
- SetTimer(timeout_window, wParam, lParam*1000, NULL);
-#ifdef ZTS
- tsrm_ls = ts_resource_ex(0, &thread_id);
- if (!tsrm_ls) {
- /* shouldn't normally happen */
- break;
- }
-#endif
- EG(timed_out) = 0;
- }
- break;
- case WM_UNREGISTER_ZEND_TIMEOUT:
- /* wParam is the thread id pointer */
- KillTimer(timeout_window, wParam);
- break;
- case WM_TIMER: {
-#ifdef ZTS
- void ***tsrm_ls;
-
- tsrm_ls = ts_resource_ex(0, &thread_id);
- if (!tsrm_ls) {
- /* Thread died before receiving its timeout? */
- break;
- }
-#endif
- KillTimer(timeout_window, wParam);
- EG(timed_out) = 1;
- }
- break;
- default:
- return DefWindowProc(hWnd, message, wParam, lParam);
- }
- return 0;
-}
-/* }}} */
-
-static unsigned __stdcall timeout_thread_proc(void *pArgs) /* {{{ */
+VOID CALLBACK tq_timer_cb(PVOID arg, BOOLEAN timed_out)
{
- MSG message;
-
- wc.style=0;
- wc.lpfnWndProc = zend_timeout_WndProc;
- wc.cbClsExtra=0;
- wc.cbWndExtra=0;
- wc.hInstance=NULL;
- wc.hIcon=NULL;
- wc.hCursor=NULL;
- wc.hbrBackground=(HBRUSH)(COLOR_BACKGROUND + 5);
- wc.lpszMenuName=NULL;
- wc.lpszClassName = "Zend Timeout Window";
- if (!RegisterClass(&wc)) {
- return -1;
- }
- timeout_window = CreateWindow(wc.lpszClassName, wc.lpszClassName, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);
- SetEvent(timeout_thread_event);
- while (GetMessage(&message, NULL, 0, 0)) {
- SendMessage(timeout_window, message.message, message.wParam, message.lParam);
- if (message.message == WM_QUIT) {
- break;
- }
- }
- DestroyWindow(timeout_window);
- UnregisterClass(wc.lpszClassName, NULL);
- SetEvent(timeout_thread_handle);
- return 0;
-}
-/* }}} */
-
-void zend_init_timeout_thread(void) /* {{{ */
-{
- timeout_thread_event = CreateEvent(NULL, FALSE, FALSE, NULL);
- timeout_thread_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
- _beginthreadex(NULL, 0, timeout_thread_proc, NULL, 0, &timeout_thread_id);
- WaitForSingleObject(timeout_thread_event, INFINITE);
-}
-/* }}} */
+ zend_bool *php_timed_out;
-void zend_shutdown_timeout_thread(void) /* {{{ */
-{
- if (!timeout_thread_initialized) {
+ /* The doc states it'll be always true, however it theoretically
+ could be FALSE when the thread was signaled. */
+ if (!timed_out) {
return;
}
- PostThreadMessage(timeout_thread_id, WM_QUIT, 0, 0);
- /* Wait for thread termination */
- WaitForSingleObject(timeout_thread_handle, 5000);
- CloseHandle(timeout_thread_handle);
- timeout_thread_initialized = 0;
+ php_timed_out = (zend_bool *)arg;
+ *php_timed_out = 1;
}
-/* }}} */
-
#endif
/* This one doesn't exists on QNX */
@@ -1283,13 +1184,28 @@ void zend_set_timeout(zend_long seconds, int reset_signals) /* {{{ */
if(!seconds) {
return;
}
- if (timeout_thread_initialized == 0 && InterlockedIncrement(&timeout_thread_initialized) == 1) {
- /* We start up this process-wide thread here and not in zend_startup(), because if Zend
- * is initialized inside a DllMain(), you're not supposed to start threads from it.
- */
- zend_init_timeout_thread();
+
+ /* Don't use ChangeTimerQueueTimer() as it will not restart an expired
+ timer, so we could end up with just an ignored timeout. Instead
+ delete and recreate. */
+ if (NULL != tq_timer) {
+ if (!DeleteTimerQueueTimer(NULL, tq_timer, NULL)) {
+ EG(timed_out) = 0;
+ tq_timer = NULL;
+ zend_error(E_ERROR, "Could not delete queued timer");
+ return;
+ }
+ tq_timer = NULL;
}
- PostThreadMessage(timeout_thread_id, WM_REGISTER_ZEND_TIMEOUT, (WPARAM) GetCurrentThreadId(), (LPARAM) seconds);
+
+ /* 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(E_ERROR, "Could not queue new timer");
+ return;
+ }
+ EG(timed_out) = 0;
#else
# ifdef HAVE_SETITIMER
{
@@ -1331,9 +1247,16 @@ void zend_set_timeout(zend_long seconds, int reset_signals) /* {{{ */
void zend_unset_timeout(TSRMLS_D) /* {{{ */
{
#ifdef ZEND_WIN32
- if(timeout_thread_initialized) {
- PostThreadMessage(timeout_thread_id, WM_UNREGISTER_ZEND_TIMEOUT, (WPARAM) GetCurrentThreadId(), (LPARAM) 0);
+ if (NULL != tq_timer) {
+ if (!DeleteTimerQueueTimer(NULL, tq_timer, NULL)) {
+ EG(timed_out) = 0;
+ tq_timer = NULL;
+ zend_error(E_ERROR, "Could not delete queued timer");
+ return;
+ }
+ tq_timer = NULL;
}
+ EG(timed_out) = 0;
#else
# ifdef HAVE_SETITIMER
if (EG(timeout_seconds)) {