Well, after half a dozen bug reports that didnt actually work... - this 
one should, could somebody comment/commit etc.

The patch includes a number of changes... -
pcntl_zend_extension_active does not appear to be getting set when using 
modules
this little magic trick to get the zval stored in the hash table for 
callbacks

+   MAKE_STD_ZVAL(handle_copy);
+        *handle_copy = **handle;
+        zval_copy_ctor(handle_copy);

I deleted this as it was confusing me alot :) - obviously not essential 
to the patch
old_pcntl_signal_handler(int signo)

added a new function
pcntl_doevents = works a bit like gtk::do_events();
basically calls any pending signal callbacks. - as the 
 pcntl_zend_extension_statement_handler did not appear to get called 
when running from a module.


best regards
alan

Index: pcntl.c
===================================================================
RCS file: /repository/php4/ext/pcntl/pcntl.c,v
retrieving revision 1.18
diff -u -r1.18 pcntl.c
--- pcntl.c    4 Jan 2002 14:08:25 -0000    1.18
+++ pcntl.c    21 Jan 2002 08:36:05 -0000
@@ -18,7 +18,7 @@
 
 /* $Id: pcntl.c,v 1.18 2002/01/04 14:08:25 hholzgra Exp $ */
 
-#define PCNTL_DEBUG 0
+#define PCNTL_DEBUG 0
 
 #if PCNTL_DEBUG
 #define DEBUG_OUT printf("DEBUG: ");printf
@@ -51,6 +51,7 @@
     PHP_FE(pcntl_wtermsig, NULL)
     PHP_FE(pcntl_wstopsig, NULL)
     PHP_FE(pcntl_exec, NULL)
+        PHP_FE(pcntl_doevents, NULL)
     {NULL, NULL, NULL}   
 };
 
@@ -208,7 +209,7 @@
 PHP_FUNCTION(pcntl_fork)
 {
     pid_t id;
-
+        pcntl_zend_extension_active=1;
     id=fork();
     if (id == -1) {
         php_error(E_ERROR, "Error %d in %s", errno, 
get_active_function_name(TSRMLS_C));
@@ -463,8 +464,9 @@
 PHP_FUNCTION(pcntl_signal)
 {
     zval **signo, **handle;
+        zval *handle_copy;
        char *func_name;
-
+      
     if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &signo, 
&handle) == FAILURE) {
         WRONG_PARAM_COUNT;
     }
@@ -474,7 +476,7 @@
     /* 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) {
-             php_error(E_WARNING, "Invalid value for handle argument 
specifEied in %s", get_active_function_name(TSRMLS_C));
+             php_error(E_WARNING, "Invalid value for handle argument 
specified in %s", get_active_function_name(TSRMLS_C));
         }
         if (php_signal(Z_LVAL_PP(signo), (Sigfunc *) 
Z_LVAL_PP(handle))==SIG_ERR) {
             php_error(E_WARNING, "Error assigning singal in %s", 
get_active_function_name(TSRMLS_C));
@@ -483,22 +485,18 @@
         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)) {
-        php_error(E_WARNING, "%s: %s is not a callable function name 
error", get_active_function_name(TSRMLS_C), func_name);
+       if (!zend_is_callable(*handle, 0, &func_name)) {
+        php_error(E_WARNING, "%s: Argument is not a callable function 
or method", 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);
-   
+        MAKE_STD_ZVAL(handle_copy);
+        *handle_copy = **handle;
+        zval_copy_ctor(handle_copy);
+       
+        zend_hash_index_update(&PCNTL_G(php_signal_table), 
Z_LVAL_PP(signo),  &handle_copy , sizeof(zval *), 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;
@@ -507,43 +505,14 @@
 }
 /* }}} */
 
-/* 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, 
&param 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);
+    DEBUG_OUT("Caught signo %d,%d,%d\n", 
signo,PCNTL_G(processing_signal_queue),pcntl_zend_extension_active);
     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;
@@ -588,59 +557,91 @@
     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;
+    zval *param, *retval;
+        zval **callback;
     char *func_name;
+        int   error;
     TSRMLS_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);
+     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) {
+                DEBUG_OUT("sig %d\n",*signal_num);
+              
+
+        if (zend_hash_index_find(&PCNTL_G(php_signal_table), 
*signal_num,  (void **) &callback)==FAILURE) {
+                        php_error(E_WARNING, "%s: Signal callback for 
%d Not found", get_active_function_name(TSRMLS_C),*signal_num);
+                        DEBUG_OUT("NOT FOUND");
             continue;
         }
+                if (!zend_is_callable( *callback, 0, &func_name)) {
+                    php_error(E_WARNING, "%s: %s is not a callable 
function or method", func_name, get_active_function_name(TSRMLS_C));
+                    continue;
+                }   
+               
         convert_to_long_ex(&param);
-        convert_to_string_ex(&call_name);
-        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, &param TSRMLS_CC);
+            ZVAL_LONG(param, *signal_num);
+         
+         /* Call php singal handler - Note that we do not report 
errors, and we ignore the return value */
+        error = call_user_function(EG(function_table), NULL,   
*callback,  retval, 1, &param   TSRMLS_CC);
+                if (error == FAILURE) {
+            php_error(E_WARNING, "Couldn't call the SIGNAL FUNCTION");
+             
+        }
     }
+    
+       
+       
     /* Clear */
-    zend_llist_clean(&PCNTL_G(php_signal_queue));
-
+     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(callback);
     efree(retval);
+     
+       
+}
+
+
+/* {{{ proto bool  pcntl_doevents()
+   Calls any pending events - if you compile pcntl as a module, the
+   statement handler does not work, you have to do it manually */
+PHP_FUNCTION(pcntl_doevents)
+{
+    zend_op_array *op_array=NULL;
+    TSRMLS_FETCH();
+
+    pcntl_zend_extension_statement_handler(op_array);
+   
+    RETURN_TRUE;   
 }
+/* }}} */
 
 /*
  * Local variables:







--------------------------  Class example --------------------


#!/opt/devel/php4/php -q
<?
dl("pcntl.so");


class test {
   
    var $run=1;
    function alarm_handle($signal){
      
             if ($signal==SIGALRM) {
                print "Caught SIGALRM!!!\n";
              
            }
    }
    function usr1_handle($signal){
             if ($signal==SIGUSR1) {
                 print "Caught SIGUSR1!!!\n";
                  $this->run = 0;
             }    
    }
   
    function start() {
        //$options=NULL;
        //$status=NULL;
        print "This test will demonstrate a fork followed by ipc via 
signals.\n";
       
        $pid=pcntl_fork();
        if ($pid==0) {
           pcntl_signal(SIGUSR1, array(&$this,"usr1_handle"));
           pcntl_signal(SIGALRM, array(&$this,"alarm_handle"));
           $this->run =1;
           while($this->run) {
               echo $this->run;
               usleep(1);
               pcntl_doevents();
             
          }
            print "ChildDone\n";
           pcntl_signal(SIGALRM, SIG_IGN); // kill parent!
            posix_kill($pid,SIGTERM); // kill myself
        } else {
           print "Parent: Waiting 10 seconds....\n";
           usleep(2);
           print "Parent: Sending SIGALRM to Child\n";
           posix_kill($pid,SIGALRM);
            sleep(2);
           print "Parent: Senging SIGUSR1 to Child\n";
           posix_kill($pid,SIGUSR1);
            sleep(2);
           print "Parent: Sending SIGALRM to Child\n";
           
           @pcntl_waitpid($pid,  $status, $options);
        }
    }
   
}

$test = new test();
$test->start();
posix_kill(posix_getpid(),SIGTERM);
 










-- 
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
To contact the list administrators, e-mail: [EMAIL PROTECTED]

Reply via email to