diff options
| author | Zeev Suraski <zeev@php.net> | 2000-06-16 14:27:28 +0000 |
|---|---|---|
| committer | Zeev Suraski <zeev@php.net> | 2000-06-16 14:27:28 +0000 |
| commit | 84eb48f0a1fd0a8be0f09ad3b77697922d2b5bfb (patch) | |
| tree | b414a535f91f70602b6e9bc29e82bab898306232 | |
| parent | 43d91224f6f54476b714eca50bd7caddb1d99ffd (diff) | |
| download | php-git-84eb48f0a1fd0a8be0f09ad3b77697922d2b5bfb.tar.gz | |
Ok, this time here's some real Win32 system programming :)
Redesigned the timeout system using a single timeout thread and a single window,
and used a much quicker check.
| -rw-r--r-- | Zend/zend.c | 13 | ||||
| -rw-r--r-- | Zend/zend_execute.c | 20 | ||||
| -rw-r--r-- | Zend/zend_execute.h | 9 | ||||
| -rw-r--r-- | Zend/zend_execute_API.c | 83 | ||||
| -rw-r--r-- | Zend/zend_globals.h | 7 |
5 files changed, 87 insertions, 45 deletions
diff --git a/Zend/zend.c b/Zend/zend.c index 7a056d7bfa..48bad64c21 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -292,9 +292,6 @@ static void executor_globals_ctor(zend_executor_globals *executor_globals) } zend_init_rsrc_plist(ELS_C); EG(lambda_count)=0; -#ifdef ZEND_WIN32 - zend_create_timeout_window(ELS_C); -#endif } @@ -302,9 +299,6 @@ static void executor_globals_dtor(zend_executor_globals *executor_globals) { zend_shutdown_constants(ELS_C); zend_destroy_rsrc_plist(ELS_C); -#ifdef ZEND_WIN32 - zend_destroy_timeout_window(ELS_C); -#endif } @@ -372,10 +366,6 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions, i zval_used_for_init.refcount = 1; zval_used_for_init.type = IS_NULL; -#ifdef ZEND_WIN32 - zend_register_timeout_wndclass(); -#endif - #ifdef ZTS global_constants_table = NULL; compiler_globals_id = ts_allocate_id(sizeof(zend_compiler_globals), (void (*)(void *)) compiler_globals_ctor, (void (*)(void *)) compiler_globals_dtor); @@ -407,6 +397,9 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions, i void zend_shutdown() { +#ifdef ZEND_WIN32 + zend_shutdown_timeout_thread(); +#endif #ifndef ZTS zend_destroy_rsrc_plist(); #endif diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 8fff13acb9..c3a08c2735 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -65,19 +65,6 @@ static void zend_extension_statement_handler(zend_extension *extension, zend_op_ static void zend_extension_fcall_begin_handler(zend_extension *extension, zend_op_array *op_array); static void zend_extension_fcall_end_handler(zend_extension *extension, zend_op_array *op_array); -#ifdef ZEND_WIN32 -#define ZEND_CHECK_TIMEOUT() \ - { \ - MSG timeout_message; \ - \ - while (PeekMessage(&timeout_message, EG(timeout_window), 0, 0, PM_REMOVE)) { \ - DispatchMessage(&timeout_message); \ - } \ - } -#else -#define ZEND_CHECK_TIMEOUT() -#endif - #define SEPARATE_ON_READ_OBJECT(obj, _type) \ if ((obj) && ((_type) == BP_VAR_R) && ((*(obj))->type == IS_OBJECT)) { \ @@ -1005,7 +992,11 @@ void execute(zend_op_array *op_array ELS_DC) #else while (1) { #endif - ZEND_CHECK_TIMEOUT(); +#ifdef ZEND_WIN32 + if (EG(timed_out)) { + zend_timeout(0); + } +#endif switch(opline->opcode) { case ZEND_ADD: EG(binary_op) = add_function; @@ -2374,6 +2365,7 @@ send_by_ref: case ZEND_NOP: NEXT_OPCODE(); EMPTY_SWITCH_DEFAULT_CASE() + } } #if SUPPORT_INTERACTIVE diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index ec7dc39ea4..553c694ba5 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -157,10 +157,13 @@ ZEND_API zend_bool zend_is_executing(void); void zend_set_timeout(long seconds); void zend_unset_timeout(void); +void zend_timeout(int dummy); + #ifdef ZEND_WIN32 -void zend_register_timeout_wndclass(void); -void zend_create_timeout_window(ELS_D); -void zend_destroy_timeout_window(ELS_D); +void zend_init_timeout_thread(); +void zend_shutdown_timeout_thread(); +#define WM_REGISTER_ZEND_TIMEOUT (WM_USER+1) +#define WM_UNREGISTER_ZEND_TIMEOUT (WM_USER+2) #endif #define zendi_zval_copy_ctor(p) zval_copy_ctor(&(p)) diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 5d1fa434d7..8ba3ff8213 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -37,8 +37,13 @@ ZEND_API void (*zend_execute)(zend_op_array *op_array ELS_DC); #ifdef ZEND_WIN32 +#include <process.h> /* true global */ static WNDCLASS wc; +static HWND timeout_window; +static HANDLE timeout_thread_event; +static DWORD timeout_thread_id; +static int timeout_thread_initialized=0; #endif @@ -137,6 +142,10 @@ void init_executor(CLS_D ELS_DC) EG(ticks_count) = 0; EG(user_error_handler) = NULL; + +#ifdef ZEND_WIN32 + EG(timed_out) = 0; +#endif } @@ -531,8 +540,7 @@ void execute_new_code(CLS_D) #endif -#if defined(HAVE_SETITIMER) || defined(ZEND_WIN32) -static void zend_timeout(int dummy) +void zend_timeout(int dummy) { ELS_FETCH(); @@ -544,7 +552,6 @@ static void zend_timeout(int dummy) zend_error(E_ERROR, "Maximum execution time of %d second%s exceeded", EG(timeout_seconds), EG(timeout_seconds) == 1 ? "" : "s"); } -#endif #ifdef ZEND_WIN32 @@ -553,18 +560,41 @@ static LRESULT CALLBACK zend_timeout_WndProc(HWND hWnd, UINT message, WPARAM wPa switch (message) { case WM_DESTROY: PostQuitMessage(0); - return 0; - case WM_TIMER: - zend_timeout(0); - return 0; + break; + case WM_REGISTER_ZEND_TIMEOUT: + /* wParam is the thread id pointer, lParam is the timeout amount in seconds */ + SetTimer(timeout_window, wParam, lParam*1000, NULL); + break; + case WM_UNREGISTER_ZEND_TIMEOUT: + /* wParam is the thread id pointer */ + KillTimer(timeout_window, wParam); + break; + case WM_TIMER: { +#ifdef ZTS + zend_executor_globals *executor_globals; + + executor_globals = ts_resource_ex(executor_globals_id, &wParam); + if (!executor_globals) { + /* 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; } -void zend_register_timeout_wndclass() + +static unsigned __stdcall timeout_thread_proc(void *pArgs) { + MSG message; + wc.style=0; wc.lpfnWndProc = zend_timeout_WndProc; wc.cbClsExtra=0; @@ -576,21 +606,38 @@ void zend_register_timeout_wndclass() wc.lpszMenuName=NULL; wc.lpszClassName = "Zend Timeout Window"; if(!RegisterClass(&wc)) { - return; + 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); + return 0; } -void zend_create_timeout_window(ELS_D) +void zend_init_timeout_thread() { - EG(timeout_window) = CreateWindow(wc.lpszClassName, wc.lpszClassName, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL); + timeout_thread_event = CreateEvent(NULL, FALSE, FALSE, NULL); + _beginthreadex(NULL, 0, timeout_thread_proc, NULL, 0, &timeout_thread_id); + WaitForSingleObject(timeout_thread_event, INFINITE); } -void zend_destroy_timeout_window(ELS_D) +void zend_shutdown_timeout_thread() { - DestroyWindow(EG(timeout_window)); + if (!timeout_thread_initialized) { + return; + } + PostThreadMessage(timeout_thread_id, WM_QUIT, 0, 0); } + #endif /* This one doesn't exists on QNX */ @@ -604,7 +651,13 @@ void zend_set_timeout(long seconds) EG(timeout_seconds) = seconds; #ifdef ZEND_WIN32 - SetTimer(EG(timeout_window), 1, seconds*1000, NULL); + 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(); + } + PostThreadMessage(timeout_thread_id, WM_REGISTER_ZEND_TIMEOUT, (WPARAM) GetCurrentThreadId(), (LPARAM) seconds); #else # ifdef HAVE_SETITIMER { @@ -626,7 +679,7 @@ void zend_unset_timeout(void) ELS_FETCH(); #ifdef ZEND_WIN32 - KillTimer(EG(timeout_window), 1); + PostThreadMessage(timeout_thread_id, WM_UNREGISTER_ZEND_TIMEOUT, (WPARAM) GetCurrentThreadId(), (LPARAM) 0); #else # ifdef HAVE_SETITIMER { diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 6bce642616..4413c34b42 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -167,6 +167,10 @@ struct _zend_executor_globals { /* for extended information support */ zend_bool no_extensions; +#ifdef ZEND_WIN32 + zend_bool timed_out; +#endif + HashTable regular_list; HashTable persistent_list; @@ -182,9 +186,6 @@ struct _zend_executor_globals { /* timeout support */ int timeout_seconds; -#ifdef ZEND_WIN32 - HWND timeout_window; -#endif int lambda_count; |
