summaryrefslogtreecommitdiff
path: root/ext/pcntl
diff options
context:
space:
mode:
authorJason Greene <jason@php.net>2001-06-19 21:42:57 +0000
committerJason Greene <jason@php.net>2001-06-19 21:42:57 +0000
commit351b78d87e98c301e39bb13d3a32ac7a97a425f8 (patch)
tree202e65307414a3a30da853c2c1462763d0ef2446 /ext/pcntl
parentd926e84e5f7824016a3e212134ab7a29abce13e8 (diff)
downloadphp-git-351b78d87e98c301e39bb13d3a32ac7a97a425f8.tar.gz
Make pcntl async safe by registering as a zend extension and grabing the
statement handler. There could possibly be a more atomic hook in the future. Also added simple TODO section to README. NOTE: sleep() grabs SIGALRM on solaris, so test-pcntl.php's alarm_handle function will not catch.
Diffstat (limited to 'ext/pcntl')
-rw-r--r--ext/pcntl/README13
-rwxr-xr-xext/pcntl/pcntl.c162
-rw-r--r--ext/pcntl/php_pcntl.h14
3 files changed, 179 insertions, 10 deletions
diff --git a/ext/pcntl/README b/ext/pcntl/README
index fe452fdb84..05f957d7e0 100644
--- a/ext/pcntl/README
+++ b/ext/pcntl/README
@@ -9,3 +9,16 @@ this functionality.
Thanks,
Jason Greeme < jason@inetgurus.net / jason@php.net >
+
+
+TODO Complete
+------------------------------------------------
+Make Async Safe X
+Implement wait.h macros as functions
+Implement setsid, setuid, etc.
+Platform Checks in config.m4
+
+
+
+
+
diff --git a/ext/pcntl/pcntl.c b/ext/pcntl/pcntl.c
index 5cdae753cb..6c14fd81c8 100755
--- a/ext/pcntl/pcntl.c
+++ b/ext/pcntl/pcntl.c
@@ -16,6 +16,14 @@
+----------------------------------------------------------------------+
*/
+#define PCNTL_DEBUG 0
+
+#if PCNTL_DEBUG
+#define DEBUG_OUT printf("DEBUG: ");printf
+#else
+#define DEBUG_OUT
+#endif
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -23,10 +31,12 @@
#include "php.h"
#include "php_ini.h"
#include "php_pcntl.h"
+#include "zend_extensions.h"
ZEND_DECLARE_MODULE_GLOBALS(pcntl)
static int le_pcntl;
+static int pcntl_zend_extension_active;
function_entry pcntl_functions[] = {
PHP_FE(pcntl_fork, NULL)
@@ -47,8 +57,33 @@ 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)
{
REGISTER_LONG_CONSTANT("SIG_IGN", (long) SIG_IGN, CONST_CS | CONST_PERSISTENT);
@@ -95,22 +130,30 @@ void php_register_signal_constants(INIT_FUNC_ARGS)
REGISTER_LONG_CONSTANT("SIGPWR", (long) SIGPWR, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SIGSYS", (long) SIGSYS, CONST_CS | CONST_PERSISTENT);
}
-
-
+
PHP_MINIT_FUNCTION(pcntl)
{
PCNTL_LS_FETCH();
php_register_signal_constants(INIT_FUNC_ARGS_PASSTHRU);
zend_hash_init(&PCNTL_G(php_signal_table), 16, NULL, NULL, 1);
+
+ /* Just in case ... */
+ memset(&PCNTL_G(php_signal_queue),0,sizeof(PCNTL_G(php_signal_queue)));
+
+ zend_llist_init(&PCNTL_G(php_signal_queue), sizeof (long), NULL, 1);
+ PCNTL_G(signal_queue_ready)=0;
+ PCNTL_G(processing_signal_queue)=0;
+ if (zend_register_extension(&pcntl_extension_entry, 0)==FAILURE)
+ return FAILURE;
return SUCCESS;
}
-
PHP_MSHUTDOWN_FUNCTION(pcntl)
{
PCNTL_LS_FETCH();
zend_hash_destroy(&PCNTL_G(php_signal_table));
+ zend_llist_destroy(&PCNTL_G(php_signal_queue));
return SUCCESS;
}
@@ -212,19 +255,20 @@ PHP_FUNCTION(pcntl_signal)
}
/* }}} */
+/* Note Old */
/* Our custom signal handler that calls the appropriate php_function */
-static void pcntl_signal_handler(int signo)
+static void old_pcntl_signal_handler(int signo)
{
char *func_name;
zval *param, *call_name, *retval;
PCNTL_LS_FETCH();
- /* printf("Caught signal: %d\n", signo); */
- if (zend_hash_index_find(&PCNTL_G(php_signal_table), (long) signo, (void *) &func_name)==FAILURE) {
- /* printf("Signl handler not fount"); */
+ 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;
}
- /* printf("Signal handler found, Calling %s\n", func_name); */
+ /* DEBUG_OUT("Signal handler found, Calling %s\n", func_name); */
MAKE_STD_ZVAL(param);
MAKE_STD_ZVAL(call_name);
MAKE_STD_ZVAL(retval);
@@ -236,11 +280,111 @@ static void pcntl_signal_handler(int signo)
zval_dtor(call_name);
efree(call_name);
- efree(param);
+ efree(param);
+ efree(retval);
+
+ return;
+}
+
+
+static void pcntl_signal_handler(int signo)
+{
+ long signal_num=signo;
+ PCNTL_LS_FETCH();
+
+ DEBUG_OUT("Caught signo %d\n", signo);
+ if (! PCNTL_G(processing_signal_queue) && pcntl_zend_extension_active ) {
+ zend_llist_add_element(&PCNTL_G(php_signal_queue), &signal_num);
+ PCNTL_G(signal_queue_ready)=1;
+ DEBUG_OUT("Added queue entry\n");
+ }
+ return;
+}
+
+
+/* Pcntl Zend Extension Hooks */
+
+int pcntl_zend_extension_startup(zend_extension *extension)
+{
+ 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)
+{
+ 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) {
+ zend_llist_element *element;
+ zval *param, *call_name, *retval;
+ char *func_name;
+ PCNTL_LS_FETCH();
+
+ /* Bail if the queue is empty or if we are already playing the queue*/
+ if (! PCNTL_G(signal_queue_ready) || PCNTL_G(processing_signal_queue))
+ return;
+
+ /* Mark our queue empty */
+ PCNTL_G(signal_queue_ready)=0;
+
+ /* If for some reason our signal queue is empty then return */
+ if (zend_llist_count(&PCNTL_G(php_signal_queue)) <= 0) {
+ return;
+ }
+
+ /* Disable queue so this function is not infinate */
+ 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) {
+ if (zend_hash_index_find(&PCNTL_G(php_signal_table), (long) *element->data, (void *) &func_name)==FAILURE) {
+ continue;
+ }
+ convert_to_long_ex(&param);
+ convert_to_string_ex(&call_name);
+ ZVAL_LONG(param, (long) *element->data);
+ 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, &param);
+ }
+ /* Clear */
+ zend_llist_clean(&PCNTL_G(php_signal_queue));
+
+ /* Re-enable queue */
+ PCNTL_G(processing_signal_queue)=0;
+
+ /* Clean up */
+ efree(param);
+ efree(call_name);
+ efree(retval);
+}
+
/*
* Local variables:
* tab-width: 4
diff --git a/ext/pcntl/php_pcntl.h b/ext/pcntl/php_pcntl.h
index a4b169a66d..be570ea110 100644
--- a/ext/pcntl/php_pcntl.h
+++ b/ext/pcntl/php_pcntl.h
@@ -20,7 +20,7 @@
#define PHP_PCNTL_H
#include "php_signal.h"
-
+#include "zend_extensions.h"
extern zend_module_entry pcntl_module_entry;
#define phpext_pcntl_ptr &pcntl_module_entry
@@ -39,10 +39,22 @@ PHP_MINFO_FUNCTION(pcntl);
PHP_FUNCTION(pcntl_fork);
PHP_FUNCTION(pcntl_waitpid);
PHP_FUNCTION(pcntl_signal);
+
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);
+
+
ZEND_BEGIN_MODULE_GLOBALS(pcntl)
HashTable php_signal_table;
+ zend_llist php_signal_queue;
+ int signal_queue_ready;
+ int processing_signal_queue;
ZEND_END_MODULE_GLOBALS(pcntl)
#ifdef ZTS