diff options
author | Jason Greene <jason@php.net> | 2002-08-22 04:20:10 +0000 |
---|---|---|
committer | Jason Greene <jason@php.net> | 2002-08-22 04:20:10 +0000 |
commit | 261a60a3604912c70b5176cde5118198ba8a1b70 (patch) | |
tree | 323e79ac5229d4615ad78448e2f08887256dacfc | |
parent | faff3a6e8a5892461486a25db178d1105017e8f5 (diff) | |
download | php-git-261a60a3604912c70b5176cde5118198ba8a1b70.tar.gz |
@Made major improvents to the pcntl extension(Jason):
@ - Greatly improved performance, by switching the signal callback mechanism
@ to use ticks
@ - Implemented object signal callback ability by using array($obj, $method)
@ - Added a restart parameter to pcntl_signal, which allows you to disable
@ the default of system call restarting
Changed callback hash table to be initialized and destroyed per reqeust
(allows the ability to use request life zvals as handles)
Nuked warnings
Modified test script to adjust to new ticks backend
Some slight WS fixes
-rwxr-xr-x | ext/pcntl/pcntl.c | 185 | ||||
-rw-r--r-- | ext/pcntl/php_pcntl.h | 10 | ||||
-rw-r--r-- | ext/pcntl/php_signal.c | 6 | ||||
-rw-r--r-- | ext/pcntl/php_signal.h | 2 | ||||
-rwxr-xr-x | ext/pcntl/test-pcntl.php | 48 |
5 files changed, 74 insertions, 177 deletions
diff --git a/ext/pcntl/pcntl.c b/ext/pcntl/pcntl.c index 2af78df9fa..d09e7aac1a 100755 --- a/ext/pcntl/pcntl.c +++ b/ext/pcntl/pcntl.c @@ -22,8 +22,9 @@ #if PCNTL_DEBUG #define DEBUG_OUT printf("DEBUG: ");printf +#define IF_DEBUG(z) z #else -#define DEBUG_OUT +#define IF_DEBUG(z) #endif #ifdef HAVE_CONFIG_H @@ -37,9 +38,6 @@ ZEND_DECLARE_MODULE_GLOBALS(pcntl) -static int le_pcntl; -static int pcntl_zend_extension_active; - function_entry pcntl_functions[] = { PHP_FE(pcntl_fork, NULL) PHP_FE(pcntl_waitpid, second_arg_force_ref) @@ -61,8 +59,8 @@ zend_module_entry pcntl_module_entry = { pcntl_functions, PHP_MINIT(pcntl), PHP_MSHUTDOWN(pcntl), - NULL, - NULL, + PHP_RINIT(pcntl), + PHP_RSHUTDOWN(pcntl), PHP_MINFO(pcntl), NO_VERSION_YET, STANDARD_MODULE_PROPERTIES @@ -70,32 +68,8 @@ zend_module_entry pcntl_module_entry = { #ifdef COMPILE_DL_PCNTL ZEND_GET_MODULE(pcntl) -#define PCNTL_ZEND_EXT ZEND_DLEXPORT -#else -#define PCNTL_ZEND_EXT #endif -PCNTL_ZEND_EXT zend_extension pcntl_extension_entry = { - "pcntl", - "1.0", - "Jason Greene", - "http://www.php.net", - "2001", - pcntl_zend_extension_startup, - pcntl_zend_extension_shutdown, - pcntl_zend_extension_activate, - pcntl_zend_extension_deactivate, - NULL, - NULL, - pcntl_zend_extension_statement_handler, - NULL, - NULL, - NULL, - NULL, - NULL -}; - - void php_register_signal_constants(INIT_FUNC_ARGS) { @@ -159,9 +133,7 @@ void php_register_signal_constants(INIT_FUNC_ARGS) } static void php_pcntl_init_globals(zend_pcntl_globals *pcntl_globals) -{ - zend_hash_init(&pcntl_globals->php_signal_table, 16, NULL, NULL, 1); - +{ /* Just in case ... */ memset(&pcntl_globals->php_signal_queue,0,sizeof(pcntl_globals->php_signal_queue)); @@ -170,30 +142,32 @@ static void php_pcntl_init_globals(zend_pcntl_globals *pcntl_globals) pcntl_globals->processing_signal_queue = 0; } -static void php_pcntl_shutdown_globals(zend_pcntl_globals *pcntl_globals) +PHP_RINIT_FUNCTION(pcntl) { - zend_hash_destroy(&pcntl_globals->php_signal_table); - zend_llist_destroy(&pcntl_globals->php_signal_queue); + zend_hash_init(&PCNTL_G(php_signal_table), 16, NULL, ZVAL_PTR_DTOR, 1); + return SUCCESS; } PHP_MINIT_FUNCTION(pcntl) { php_register_signal_constants(INIT_FUNC_ARGS_PASSTHRU); - ZEND_INIT_MODULE_GLOBALS(pcntl, php_pcntl_init_globals, php_pcntl_shutdown_globals); - if (zend_register_extension(&pcntl_extension_entry, 0)==FAILURE) - return FAILURE; + ZEND_INIT_MODULE_GLOBALS(pcntl, php_pcntl_init_globals, NULL); + php_add_tick_function(pcntl_tick_handler); + return SUCCESS; } PHP_MSHUTDOWN_FUNCTION(pcntl) { - zend_hash_destroy(&PCNTL_G(php_signal_table)); zend_llist_destroy(&PCNTL_G(php_signal_queue)); return SUCCESS; } - - +PHP_RSHUTDOWN_FUNCTION(pcntl) +{ + zend_hash_destroy(&PCNTL_G(php_signal_table)); + return SUCCESS; +} PHP_MINFO_FUNCTION(pcntl) { @@ -475,141 +449,69 @@ PHP_FUNCTION(pcntl_exec) } /* }}} */ -/* {{{ proto bool pcntl_signal(long signo, mixed handle) +/* {{{ proto bool pcntl_signal(long signo, mixed handle, [bool restart_syscalls]) Assigns a system signal handler to a PHP function */ PHP_FUNCTION(pcntl_signal) { - zval **signo, **handle; + zval *handle, **dest_handle = NULL; char *func_name; + long signo; + zend_bool restart_syscalls = 1; - if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &signo, &handle) == FAILURE) { - WRONG_PARAM_COUNT; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz|b", &signo, &handle, &restart_syscalls) == FAILURE) { + return; } - convert_to_long_ex(signo); - /* Special long value case for SIG_DFL and SIG_IGN */ - if (Z_TYPE_PP(handle)==IS_LONG) { - if (Z_LVAL_PP(handle)!= (long) SIG_DFL && Z_LVAL_PP(handle) != (long) SIG_IGN) { + if (Z_TYPE_P(handle)==IS_LONG) { + if (Z_LVAL_P(handle)!= (long) SIG_DFL && Z_LVAL_P(handle) != (long) SIG_IGN) { php_error(E_WARNING, "Invalid value for handle argument specifEied in %s", get_active_function_name(TSRMLS_C)); } - if (php_signal(Z_LVAL_PP(signo), (Sigfunc *) Z_LVAL_PP(handle))==SIG_ERR) { + if (php_signal(signo, (Sigfunc *) Z_LVAL_P(handle), (int) restart_syscalls) == SIG_ERR) { php_error(E_WARNING, "Error assigning singal in %s", get_active_function_name(TSRMLS_C)); RETURN_FALSE; } RETURN_TRUE; } - if (Z_TYPE_PP(handle) != IS_STRING) { - php_error(E_WARNING, "Invalid type specified for handle argument in %s", get_active_function_name(TSRMLS_C)); - RETURN_FALSE; - } - - convert_to_string_ex(handle); /* Just in case */ - if (!zend_is_callable(*handle, 0, &func_name)) { + if (!zend_is_callable(handle, 0, &func_name)) { php_error(E_WARNING, "%s: %s is not a callable function name error", get_active_function_name(TSRMLS_C), func_name); efree(func_name); RETURN_FALSE; } efree(func_name); - - /* Add the function name to our signal table */ - zend_hash_index_update(&PCNTL_G(php_signal_table), Z_LVAL_PP(signo), Z_STRVAL_PP(handle), (Z_STRLEN_PP(handle) + 1) * sizeof(char), NULL); - if (php_signal(Z_LVAL_PP(signo), pcntl_signal_handler)==SIG_ERR) { - php_error(E_WARNING, "Error assigning singal in %s", get_active_function_name(TSRMLS_C)); - RETURN_FALSE; + /* Add the function name to our signal table */ + zend_hash_index_update(&PCNTL_G(php_signal_table), signo, (void **) &handle, sizeof(zval *), (void **) &dest_handle); + if (dest_handle) zval_add_ref(dest_handle); + + if (php_signal(signo, pcntl_signal_handler, (int) restart_syscalls) == SIG_ERR) { + php_error(E_WARNING, "Error assigning singal in %s", get_active_function_name(TSRMLS_C)); + RETURN_FALSE; } RETURN_TRUE; } /* }}} */ -/* Note Old */ -static void old_pcntl_signal_handler(int signo) -{ - char *func_name; - zval *param, *call_name, *retval; - TSRMLS_FETCH(); - - DEBUG_OUT("Caught signal: %d\n", signo); - if (zend_hash_index_find(&PCNTL_G(php_signal_table), (long) signo, (void *) &func_name)==FAILURE) { - DEBUG_OUT("Signl handler not fount"); - return; - } - /* DEBUG_OUT("Signal handler found, Calling %s\n", func_name); */ - MAKE_STD_ZVAL(param); - MAKE_STD_ZVAL(call_name); - MAKE_STD_ZVAL(retval); - ZVAL_LONG(param, signo); - ZVAL_STRING(call_name, func_name, 1); - - /* Call php singal handler - Note that we do not report errors, and we ignore the return value */ - call_user_function(EG(function_table), NULL, call_name, retval, 1, ¶m TSRMLS_CC); - - zval_dtor(call_name); - efree(call_name); - efree(param); - efree(retval); - - return; -} - /* Our custom signal handler that calls the appropriate php_function */ static void pcntl_signal_handler(int signo) { long signal_num = signo; TSRMLS_FETCH(); - DEBUG_OUT("Caught signo %d\n", signo); - if (! PCNTL_G(processing_signal_queue) && pcntl_zend_extension_active ) { + IF_DEBUG(DEBUG_OUT("Caught signo %d\n", signo)); + if (! PCNTL_G(processing_signal_queue)) { zend_llist_add_element(&PCNTL_G(php_signal_queue), &signal_num); PCNTL_G(signal_queue_ready) = 1; - DEBUG_OUT("Added queue entry\n"); + IF_DEBUG(DEBUG_OUT("Added queue entry\n")); } return; } -/* Pcntl Zend Extension Hooks */ - -int pcntl_zend_extension_startup(zend_extension *extension) -{ - TSRMLS_FETCH(); - - DEBUG_OUT("Statup Called\n"); - pcntl_zend_extension_active = 1; - CG(extended_info) = 1; - return SUCCESS; -} - -void pcntl_zend_extension_shutdown(zend_extension *extension) -{ - DEBUG_OUT("Shutdown Called\n"); - return; -} - -void pcntl_zend_extension_activate(void) -{ - TSRMLS_FETCH(); - - DEBUG_OUT("Activate Called\n"); - pcntl_zend_extension_active = 1; - CG(extended_info) = 1; - return; -} - -void pcntl_zend_extension_deactivate(void) -{ - DEBUG_OUT("Deactivate Called\n"); - pcntl_zend_extension_active = 0; - return; -} - -/* Custom hook to ensure signals only get called at a safe poing in Zend's execute process */ -void pcntl_zend_extension_statement_handler(zend_op_array *op_array) +void pcntl_tick_handler() { zend_llist_element *element; - zval *param, *call_name, *retval; - char *func_name; + zval *param, **handle, *retval; TSRMLS_FETCH(); /* Bail if the queue is empty or if we are already playing the queue*/ @@ -624,26 +526,24 @@ void pcntl_zend_extension_statement_handler(zend_op_array *op_array) return; } - /* Disable queue so this function is not infinate */ + /* Prevent reentrant handler calls */ PCNTL_G(processing_signal_queue) = 1; /* Allocate */ MAKE_STD_ZVAL(param); - MAKE_STD_ZVAL(call_name); MAKE_STD_ZVAL(retval); /* Traverse through our signal queue and call the appropriate php functions */ for (element = (&PCNTL_G(php_signal_queue))->head; element; element = element->next) { long *signal_num = (long *)&element->data; - if (zend_hash_index_find(&PCNTL_G(php_signal_table), *signal_num, (void *) &func_name)==FAILURE) { + if (zend_hash_index_find(&PCNTL_G(php_signal_table), *signal_num, (void **) &handle)==FAILURE) { continue; } ZVAL_LONG(param, *signal_num); - ZVAL_STRING(call_name, func_name, 0); - /* Call php singal handler - Note that we do not report errors, and we ignore the return value */ - call_user_function(EG(function_table), NULL, call_name, retval, 1, ¶m TSRMLS_CC); + /* Call php singal handler - Note that we do not report errors, and we ignore the eturn value */ + call_user_function(EG(function_table), NULL, *handle, retval, 1, ¶m TSRMLS_CC); } /* Clear */ zend_llist_clean(&PCNTL_G(php_signal_queue)); @@ -653,7 +553,6 @@ void pcntl_zend_extension_statement_handler(zend_op_array *op_array) /* Clean up */ efree(param); - efree(call_name); efree(retval); } diff --git a/ext/pcntl/php_pcntl.h b/ext/pcntl/php_pcntl.h index f06cbcddf2..b982d33102 100644 --- a/ext/pcntl/php_pcntl.h +++ b/ext/pcntl/php_pcntl.h @@ -23,7 +23,7 @@ #include <sys/wait.h> #include "php_signal.h" -#include "zend_extensions.h" +#include "php_ticks.h" extern zend_module_entry pcntl_module_entry; #define phpext_pcntl_ptr &pcntl_module_entry @@ -52,13 +52,7 @@ PHP_FUNCTION(pcntl_signal); PHP_FUNCTION(pcntl_exec); static void pcntl_signal_handler(int); - -/* Zend extension prototypes */ -int pcntl_zend_extension_startup(zend_extension *extension); -void pcntl_zend_extension_shutdown(zend_extension *extension); -void pcntl_zend_extension_activate(void); -void pcntl_zend_extension_deactivate(void); -void pcntl_zend_extension_statement_handler(zend_op_array *op_array); +static void pcntl_tick_handler(); ZEND_BEGIN_MODULE_GLOBALS(pcntl) diff --git a/ext/pcntl/php_signal.c b/ext/pcntl/php_signal.c index 41172a988b..840eb46b44 100644 --- a/ext/pcntl/php_signal.c +++ b/ext/pcntl/php_signal.c @@ -20,16 +20,16 @@ #include "php_signal.h" -/* php_signal using sigaction is taken verbatim from Advanced Programing +/* php_signal using sigaction is derrived from Advanced Programing * in the Unix Environment by W. Richard Stevens p 298. */ -Sigfunc *php_signal(int signo, Sigfunc *func) +Sigfunc *php_signal(int signo, Sigfunc *func, int restart) { struct sigaction act,oact; act.sa_handler = func; sigemptyset(&act.sa_mask); act.sa_flags = 0; - if (signo == SIGALRM) { + if (signo == SIGALRM || (! restart)) { #ifdef SA_INTERRUPT act.sa_flags |= SA_INTERRUPT; /* SunOS */ #endif diff --git a/ext/pcntl/php_signal.h b/ext/pcntl/php_signal.h index 63baa4c3a3..e4657a68af 100644 --- a/ext/pcntl/php_signal.h +++ b/ext/pcntl/php_signal.h @@ -23,6 +23,6 @@ #define PHP_SIGNAL_H typedef void Sigfunc(int); -Sigfunc *php_signal(int signo, Sigfunc *func); +Sigfunc *php_signal(int signo, Sigfunc *func, int restart); #endif diff --git a/ext/pcntl/test-pcntl.php b/ext/pcntl/test-pcntl.php index 41334ba814..6b3ee5649e 100755 --- a/ext/pcntl/test-pcntl.php +++ b/ext/pcntl/test-pcntl.php @@ -1,35 +1,39 @@ -#!/opt/devel/php4/php -q +#!../../php -q <? + +declare(ticks=1); + function alarm_handle($signal){ if ($signal==SIGALRM) print "Caught SIGALRM!!!\n"; } + function usr1_handle($signal){ - if ($signal==SIGUSR1) print "Caught SIGUSR1!!!\n"; + if ($signal==SIGUSR1) print "Caught SIGUSR1!!!\n"; } print "This test will demonstrate a fork followed by ipc via signals.\n"; $pid=pcntl_fork(); if ($pid==0) { - pcntl_signal(SIGUSR1, "usr1_handle"); - pcntl_signal(SIGALRM, "alarm_handle"); - print "Child: Waiting for alarm.....\n"; - sleep(100); - print "Child: Waiting for usr1......\n"; - sleep(100); - print "Child: Resetting Alarm handler to Ignore....\n"; - pcntl_signal(SIGALRM, SIG_IGN); - sleep(10); - print "Done\n"; + pcntl_signal(SIGUSR1, "usr1_handle"); + pcntl_signal(SIGALRM, "alarm_handle"); + print "Child: Waiting for alarm.....\n"; + sleep(100); + print "Child: Waiting for usr1......\n"; + sleep(100); + print "Child: Resetting Alarm handler to Ignore....\n"; + pcntl_signal(SIGALRM, SIG_IGN); + sleep(10); + print "Done\n"; } else { - print "Parent: Waiting 10 seconds....\n"; - sleep(10); - print "Parent: Sending SIGALRM to Child\n"; - posix_kill($pid,SIGALRM); - sleep(1); - print "Parent: Senging SIGUSR1 to Child\n"; - posix_kill($pid,SIGUSR1); - sleep(1); - print "Parent: Sending SIGALRM to Child\n"; - pcntl_waitpid($pid, &$status, $options); + print "Parent: Waiting 10 seconds....\n"; + sleep(10); + print "Parent: Sending SIGALRM to Child\n"; + posix_kill($pid,SIGALRM); + sleep(1); + print "Parent: Senging SIGUSR1 to Child\n"; + posix_kill($pid,SIGUSR1); + sleep(1); + print "Parent: Sending SIGALRM to Child\n"; + pcntl_waitpid($pid, &$status, $options); } |