PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/pcntl - pcntl.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 438 524 83.6 %
Date: 2016-09-18 Functions: 32 36 88.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 7                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2016 The PHP Group                                |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 3.01 of the PHP license,      |
       8             :    | that is bundled with this package in the file LICENSE, and is        |
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.php.net/license/3_01.txt                                  |
      11             :    | If you did not receive a copy of the PHP license and are unable to   |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@php.net so we can mail you a copy immediately.               |
      14             :    +----------------------------------------------------------------------+
      15             :    | Author: Jason Greene <jason@inetgurus.net>                           |
      16             :    +----------------------------------------------------------------------+
      17             :  */
      18             : 
      19             : /* $Id$ */
      20             : 
      21             : #define PCNTL_DEBUG 0
      22             : 
      23             : #if PCNTL_DEBUG
      24             : #define DEBUG_OUT printf("DEBUG: ");printf
      25             : #define IF_DEBUG(z) z
      26             : #else
      27             : #define IF_DEBUG(z)
      28             : #endif
      29             : 
      30             : #ifdef HAVE_CONFIG_H
      31             : #include "config.h"
      32             : #endif
      33             : 
      34             : #include "php.h"
      35             : #include "php_ini.h"
      36             : #include "ext/standard/info.h"
      37             : #include "php_pcntl.h"
      38             : #include "php_signal.h"
      39             : #include "php_ticks.h"
      40             : 
      41             : #if HAVE_GETPRIORITY || HAVE_SETPRIORITY || HAVE_WAIT3
      42             : #include <sys/wait.h>
      43             : #include <sys/time.h>
      44             : #include <sys/resource.h>
      45             : #endif
      46             : 
      47             : #include <errno.h>
      48             : 
      49             : ZEND_DECLARE_MODULE_GLOBALS(pcntl)
      50             : static PHP_GINIT_FUNCTION(pcntl);
      51             : 
      52             : /* {{{ arginfo */
      53             : ZEND_BEGIN_ARG_INFO(arginfo_pcntl_void, 0)
      54             : ZEND_END_ARG_INFO()
      55             : 
      56             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_waitpid, 0, 0, 2)
      57             :         ZEND_ARG_INFO(0, pid)
      58             :         ZEND_ARG_INFO(1, status)
      59             :         ZEND_ARG_INFO(0, options)
      60             :         ZEND_ARG_INFO(1, rusage)
      61             : ZEND_END_ARG_INFO()
      62             : 
      63             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_wait, 0, 0, 1)
      64             :         ZEND_ARG_INFO(1, status)
      65             :         ZEND_ARG_INFO(0, options)
      66             :         ZEND_ARG_INFO(1, rusage)
      67             : ZEND_END_ARG_INFO()
      68             : 
      69             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_signal, 0, 0, 2)
      70             :         ZEND_ARG_INFO(0, signo)
      71             :         ZEND_ARG_INFO(0, handler)
      72             :         ZEND_ARG_INFO(0, restart_syscalls)
      73             : ZEND_END_ARG_INFO()
      74             : 
      75             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_signal_get_handler, 0, 0, 1)
      76             :         ZEND_ARG_INFO(0, signo)
      77             : ZEND_END_ARG_INFO()
      78             : 
      79             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_sigprocmask, 0, 0, 2)
      80             :         ZEND_ARG_INFO(0, how)
      81             :         ZEND_ARG_INFO(0, set)
      82             :         ZEND_ARG_INFO(1, oldset)
      83             : ZEND_END_ARG_INFO()
      84             : 
      85             : #ifdef HAVE_STRUCT_SIGINFO_T
      86             : # if HAVE_SIGWAITINFO && HAVE_SIGTIMEDWAIT
      87             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_sigwaitinfo, 0, 0, 1)
      88             :         ZEND_ARG_INFO(0, set)
      89             :         ZEND_ARG_INFO(1, info)
      90             : ZEND_END_ARG_INFO()
      91             : 
      92             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_sigtimedwait, 0, 0, 1)
      93             :         ZEND_ARG_INFO(0, set)
      94             :         ZEND_ARG_INFO(1, info)
      95             :         ZEND_ARG_INFO(0, seconds)
      96             :         ZEND_ARG_INFO(0, nanoseconds)
      97             : ZEND_END_ARG_INFO()
      98             : # endif
      99             : #endif
     100             : 
     101             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_wifexited, 0, 0, 1)
     102             :         ZEND_ARG_INFO(0, status)
     103             : ZEND_END_ARG_INFO()
     104             : 
     105             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_wifstopped, 0, 0, 1)
     106             :         ZEND_ARG_INFO(0, status)
     107             : ZEND_END_ARG_INFO()
     108             : 
     109             : #ifdef HAVE_WCONTINUED
     110             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_wifcontinued, 0, 0, 1)
     111             :         ZEND_ARG_INFO(0, status)
     112             : ZEND_END_ARG_INFO()
     113             : #endif
     114             : 
     115             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_wifsignaled, 0, 0, 1)
     116             :         ZEND_ARG_INFO(0, status)
     117             : ZEND_END_ARG_INFO()
     118             : 
     119             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_wifexitstatus, 0, 0, 1)
     120             :         ZEND_ARG_INFO(0, status)
     121             : ZEND_END_ARG_INFO()
     122             : 
     123             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_wtermsig, 0, 0, 1)
     124             :         ZEND_ARG_INFO(0, status)
     125             : ZEND_END_ARG_INFO()
     126             : 
     127             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_wstopsig, 0, 0, 1)
     128             :         ZEND_ARG_INFO(0, status)
     129             : ZEND_END_ARG_INFO()
     130             : 
     131             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_exec, 0, 0, 1)
     132             :         ZEND_ARG_INFO(0, path)
     133             :         ZEND_ARG_INFO(0, args)
     134             :         ZEND_ARG_INFO(0, envs)
     135             : ZEND_END_ARG_INFO()
     136             : 
     137             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_alarm, 0, 0, 1)
     138             :         ZEND_ARG_INFO(0, seconds)
     139             : ZEND_END_ARG_INFO()
     140             : 
     141             : #ifdef HAVE_GETPRIORITY
     142             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_getpriority, 0, 0, 0)
     143             :         ZEND_ARG_INFO(0, pid)
     144             :         ZEND_ARG_INFO(0, process_identifier)
     145             : ZEND_END_ARG_INFO()
     146             : #endif
     147             : 
     148             : #ifdef HAVE_SETPRIORITY
     149             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_setpriority, 0, 0, 1)
     150             :         ZEND_ARG_INFO(0, priority)
     151             :         ZEND_ARG_INFO(0, pid)
     152             :         ZEND_ARG_INFO(0, process_identifier)
     153             : ZEND_END_ARG_INFO()
     154             : #endif
     155             : 
     156             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_strerror, 0, 0, 1)
     157             :         ZEND_ARG_INFO(0, errno)
     158             : ZEND_END_ARG_INFO()
     159             : 
     160             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_async_signals, 0, 0, 1)
     161             :         ZEND_ARG_INFO(0, on)
     162             : ZEND_END_ARG_INFO()
     163             : /* }}} */
     164             : 
     165             : const zend_function_entry pcntl_functions[] = {
     166             :         PHP_FE(pcntl_fork,                      arginfo_pcntl_void)
     167             :         PHP_FE(pcntl_waitpid,           arginfo_pcntl_waitpid)
     168             :         PHP_FE(pcntl_wait,                      arginfo_pcntl_wait)
     169             :         PHP_FE(pcntl_signal,            arginfo_pcntl_signal)
     170             :         PHP_FE(pcntl_signal_get_handler,                arginfo_pcntl_signal_get_handler)
     171             :         PHP_FE(pcntl_signal_dispatch,   arginfo_pcntl_void)
     172             :         PHP_FE(pcntl_wifexited,         arginfo_pcntl_wifexited)
     173             :         PHP_FE(pcntl_wifstopped,        arginfo_pcntl_wifstopped)
     174             :         PHP_FE(pcntl_wifsignaled,       arginfo_pcntl_wifsignaled)
     175             :         PHP_FE(pcntl_wexitstatus,       arginfo_pcntl_wifexitstatus)
     176             :         PHP_FE(pcntl_wtermsig,          arginfo_pcntl_wtermsig)
     177             :         PHP_FE(pcntl_wstopsig,          arginfo_pcntl_wstopsig)
     178             :         PHP_FE(pcntl_exec,                      arginfo_pcntl_exec)
     179             :         PHP_FE(pcntl_alarm,                     arginfo_pcntl_alarm)
     180             :         PHP_FE(pcntl_get_last_error,    arginfo_pcntl_void)
     181             :         PHP_FALIAS(pcntl_errno, pcntl_get_last_error,   NULL)
     182             :         PHP_FE(pcntl_strerror,          arginfo_pcntl_strerror) 
     183             : #ifdef HAVE_GETPRIORITY
     184             :         PHP_FE(pcntl_getpriority,       arginfo_pcntl_getpriority)
     185             : #endif
     186             : #ifdef HAVE_SETPRIORITY
     187             :         PHP_FE(pcntl_setpriority,       arginfo_pcntl_setpriority)
     188             : #endif
     189             : #ifdef HAVE_SIGPROCMASK
     190             :         PHP_FE(pcntl_sigprocmask,       arginfo_pcntl_sigprocmask)
     191             : #endif
     192             : #ifdef HAVE_STRUCT_SIGINFO_T
     193             : # if HAVE_SIGWAITINFO && HAVE_SIGTIMEDWAIT
     194             :         PHP_FE(pcntl_sigwaitinfo,       arginfo_pcntl_sigwaitinfo)
     195             :         PHP_FE(pcntl_sigtimedwait,      arginfo_pcntl_sigtimedwait)
     196             : # endif
     197             : #endif
     198             : #ifdef HAVE_WCONTINUED
     199             :         PHP_FE(pcntl_wifcontinued,      arginfo_pcntl_wifcontinued)
     200             : #endif
     201             :         PHP_FE(pcntl_async_signals,     arginfo_pcntl_async_signals)
     202             :         PHP_FE_END
     203             : };
     204             : 
     205             : zend_module_entry pcntl_module_entry = {
     206             :         STANDARD_MODULE_HEADER,
     207             :         "pcntl",
     208             :         pcntl_functions,
     209             :         PHP_MINIT(pcntl),
     210             :         PHP_MSHUTDOWN(pcntl),
     211             :         PHP_RINIT(pcntl),
     212             :         PHP_RSHUTDOWN(pcntl),
     213             :         PHP_MINFO(pcntl),
     214             :         PHP_PCNTL_VERSION,
     215             :         PHP_MODULE_GLOBALS(pcntl),
     216             :         PHP_GINIT(pcntl),
     217             :         NULL,
     218             :         NULL,
     219             :         STANDARD_MODULE_PROPERTIES_EX
     220             : };
     221             : 
     222             : #ifdef COMPILE_DL_PCNTL
     223             : ZEND_GET_MODULE(pcntl)
     224             : #endif
     225             : 
     226             : static void (*orig_interrupt_function)(zend_execute_data *execute_data);
     227             : 
     228             : #ifdef HAVE_STRUCT_SIGINFO_T
     229             : static void pcntl_signal_handler(int, siginfo_t*, void*);
     230             : static void pcntl_siginfo_to_zval(int, siginfo_t*, zval*);
     231             : #else
     232             : static void pcntl_signal_handler(int);
     233             : #endif
     234             : static void pcntl_signal_dispatch();
     235             : static void pcntl_interrupt_function(zend_execute_data *execute_data);
     236             : 
     237       23922 : void php_register_signal_constants(INIT_FUNC_ARGS)
     238             : {
     239             : 
     240             :         /* Wait Constants */
     241             : #ifdef WNOHANG
     242       23922 :         REGISTER_LONG_CONSTANT("WNOHANG",  (zend_long) WNOHANG, CONST_CS | CONST_PERSISTENT);
     243             : #endif
     244             : #ifdef WUNTRACED
     245       23922 :         REGISTER_LONG_CONSTANT("WUNTRACED",  (zend_long) WUNTRACED, CONST_CS | CONST_PERSISTENT);
     246             : #endif
     247             : #ifdef HAVE_WCONTINUED
     248       23922 :         REGISTER_LONG_CONSTANT("WCONTINUED",  (zend_long) WCONTINUED, CONST_CS | CONST_PERSISTENT);
     249             : #endif
     250             : 
     251             :         /* Signal Constants */
     252       23922 :         REGISTER_LONG_CONSTANT("SIG_IGN",  (zend_long) SIG_IGN, CONST_CS | CONST_PERSISTENT);
     253       23922 :         REGISTER_LONG_CONSTANT("SIG_DFL",  (zend_long) SIG_DFL, CONST_CS | CONST_PERSISTENT);
     254       23922 :         REGISTER_LONG_CONSTANT("SIG_ERR",  (zend_long) SIG_ERR, CONST_CS | CONST_PERSISTENT);
     255       23922 :         REGISTER_LONG_CONSTANT("SIGHUP",   (zend_long) SIGHUP,  CONST_CS | CONST_PERSISTENT);
     256       23922 :         REGISTER_LONG_CONSTANT("SIGINT",   (zend_long) SIGINT,  CONST_CS | CONST_PERSISTENT);
     257       23922 :         REGISTER_LONG_CONSTANT("SIGQUIT",  (zend_long) SIGQUIT, CONST_CS | CONST_PERSISTENT);
     258       23922 :         REGISTER_LONG_CONSTANT("SIGILL",   (zend_long) SIGILL,  CONST_CS | CONST_PERSISTENT);
     259       23922 :         REGISTER_LONG_CONSTANT("SIGTRAP",  (zend_long) SIGTRAP, CONST_CS | CONST_PERSISTENT);
     260       23922 :         REGISTER_LONG_CONSTANT("SIGABRT",  (zend_long) SIGABRT, CONST_CS | CONST_PERSISTENT);
     261             : #ifdef SIGIOT
     262       23922 :         REGISTER_LONG_CONSTANT("SIGIOT",   (zend_long) SIGIOT,  CONST_CS | CONST_PERSISTENT);
     263             : #endif
     264       23922 :         REGISTER_LONG_CONSTANT("SIGBUS",   (zend_long) SIGBUS,  CONST_CS | CONST_PERSISTENT);
     265       23922 :         REGISTER_LONG_CONSTANT("SIGFPE",   (zend_long) SIGFPE,  CONST_CS | CONST_PERSISTENT);
     266       23922 :         REGISTER_LONG_CONSTANT("SIGKILL",  (zend_long) SIGKILL, CONST_CS | CONST_PERSISTENT);
     267       23922 :         REGISTER_LONG_CONSTANT("SIGUSR1",  (zend_long) SIGUSR1, CONST_CS | CONST_PERSISTENT);
     268       23922 :         REGISTER_LONG_CONSTANT("SIGSEGV",  (zend_long) SIGSEGV, CONST_CS | CONST_PERSISTENT);
     269       23922 :         REGISTER_LONG_CONSTANT("SIGUSR2",  (zend_long) SIGUSR2, CONST_CS | CONST_PERSISTENT);
     270       23922 :         REGISTER_LONG_CONSTANT("SIGPIPE",  (zend_long) SIGPIPE, CONST_CS | CONST_PERSISTENT);
     271       23922 :         REGISTER_LONG_CONSTANT("SIGALRM",  (zend_long) SIGALRM, CONST_CS | CONST_PERSISTENT);
     272       23922 :         REGISTER_LONG_CONSTANT("SIGTERM",  (zend_long) SIGTERM, CONST_CS | CONST_PERSISTENT);
     273             : #ifdef SIGSTKFLT
     274       23922 :         REGISTER_LONG_CONSTANT("SIGSTKFLT",(zend_long) SIGSTKFLT, CONST_CS | CONST_PERSISTENT);
     275             : #endif
     276             : #ifdef SIGCLD
     277       23922 :         REGISTER_LONG_CONSTANT("SIGCLD",   (zend_long) SIGCLD, CONST_CS | CONST_PERSISTENT);
     278             : #endif
     279             : #ifdef SIGCHLD
     280       23922 :         REGISTER_LONG_CONSTANT("SIGCHLD",  (zend_long) SIGCHLD, CONST_CS | CONST_PERSISTENT);
     281             : #endif
     282       23922 :         REGISTER_LONG_CONSTANT("SIGCONT",  (zend_long) SIGCONT, CONST_CS | CONST_PERSISTENT);
     283       23922 :         REGISTER_LONG_CONSTANT("SIGSTOP",  (zend_long) SIGSTOP, CONST_CS | CONST_PERSISTENT);
     284       23922 :         REGISTER_LONG_CONSTANT("SIGTSTP",  (zend_long) SIGTSTP, CONST_CS | CONST_PERSISTENT);
     285       23922 :         REGISTER_LONG_CONSTANT("SIGTTIN",  (zend_long) SIGTTIN, CONST_CS | CONST_PERSISTENT);
     286       23922 :         REGISTER_LONG_CONSTANT("SIGTTOU",  (zend_long) SIGTTOU, CONST_CS | CONST_PERSISTENT);
     287       23922 :         REGISTER_LONG_CONSTANT("SIGURG",   (zend_long) SIGURG , CONST_CS | CONST_PERSISTENT);
     288       23922 :         REGISTER_LONG_CONSTANT("SIGXCPU",  (zend_long) SIGXCPU, CONST_CS | CONST_PERSISTENT);
     289       23922 :         REGISTER_LONG_CONSTANT("SIGXFSZ",  (zend_long) SIGXFSZ, CONST_CS | CONST_PERSISTENT);
     290       23922 :         REGISTER_LONG_CONSTANT("SIGVTALRM",(zend_long) SIGVTALRM, CONST_CS | CONST_PERSISTENT);
     291       23922 :         REGISTER_LONG_CONSTANT("SIGPROF",  (zend_long) SIGPROF, CONST_CS | CONST_PERSISTENT);
     292       23922 :         REGISTER_LONG_CONSTANT("SIGWINCH", (zend_long) SIGWINCH, CONST_CS | CONST_PERSISTENT);
     293             : #ifdef SIGPOLL
     294       23922 :         REGISTER_LONG_CONSTANT("SIGPOLL",  (zend_long) SIGPOLL, CONST_CS | CONST_PERSISTENT);
     295             : #endif
     296       23922 :         REGISTER_LONG_CONSTANT("SIGIO",    (zend_long) SIGIO, CONST_CS | CONST_PERSISTENT);
     297             : #ifdef SIGPWR
     298       23922 :         REGISTER_LONG_CONSTANT("SIGPWR",   (zend_long) SIGPWR, CONST_CS | CONST_PERSISTENT);
     299             : #endif
     300             : #ifdef SIGSYS
     301       23922 :         REGISTER_LONG_CONSTANT("SIGSYS",   (zend_long) SIGSYS, CONST_CS | CONST_PERSISTENT);
     302       23922 :         REGISTER_LONG_CONSTANT("SIGBABY",  (zend_long) SIGSYS, CONST_CS | CONST_PERSISTENT);
     303             : #endif
     304             : 
     305             : #if HAVE_GETPRIORITY || HAVE_SETPRIORITY
     306       23922 :         REGISTER_LONG_CONSTANT("PRIO_PGRP", PRIO_PGRP, CONST_CS | CONST_PERSISTENT);
     307       23922 :         REGISTER_LONG_CONSTANT("PRIO_USER", PRIO_USER, CONST_CS | CONST_PERSISTENT);
     308       23922 :         REGISTER_LONG_CONSTANT("PRIO_PROCESS", PRIO_PROCESS, CONST_CS | CONST_PERSISTENT);
     309             : #endif
     310             : 
     311             :         /* {{{ "how" argument for sigprocmask */
     312             : #ifdef HAVE_SIGPROCMASK
     313       23922 :         REGISTER_LONG_CONSTANT("SIG_BLOCK",   SIG_BLOCK, CONST_CS | CONST_PERSISTENT);
     314       23922 :         REGISTER_LONG_CONSTANT("SIG_UNBLOCK", SIG_UNBLOCK, CONST_CS | CONST_PERSISTENT);
     315       23922 :         REGISTER_LONG_CONSTANT("SIG_SETMASK", SIG_SETMASK, CONST_CS | CONST_PERSISTENT);
     316             : #endif
     317             :         /* }}} */
     318             : 
     319             :         /* {{{ si_code */
     320             : #if HAVE_SIGWAITINFO && HAVE_SIGTIMEDWAIT
     321       23922 :         REGISTER_LONG_CONSTANT("SI_USER",    SI_USER,    CONST_CS | CONST_PERSISTENT);
     322             : #ifdef SI_NOINFO
     323             :         REGISTER_LONG_CONSTANT("SI_NOINFO",  SI_NOINFO,  CONST_CS | CONST_PERSISTENT);
     324             : #endif
     325             : #ifdef SI_KERNEL
     326       23922 :         REGISTER_LONG_CONSTANT("SI_KERNEL",  SI_KERNEL,  CONST_CS | CONST_PERSISTENT);
     327             : #endif
     328       23922 :         REGISTER_LONG_CONSTANT("SI_QUEUE",   SI_QUEUE,   CONST_CS | CONST_PERSISTENT);
     329       23922 :         REGISTER_LONG_CONSTANT("SI_TIMER",   SI_TIMER,   CONST_CS | CONST_PERSISTENT);
     330       23922 :         REGISTER_LONG_CONSTANT("SI_MESGQ",   SI_MESGQ,   CONST_CS | CONST_PERSISTENT);
     331       23922 :         REGISTER_LONG_CONSTANT("SI_ASYNCIO", SI_ASYNCIO, CONST_CS | CONST_PERSISTENT);
     332             : #ifdef SI_SIGIO
     333       23922 :         REGISTER_LONG_CONSTANT("SI_SIGIO",   SI_SIGIO,   CONST_CS | CONST_PERSISTENT);
     334             : #endif
     335             : #ifdef SI_TKILL
     336       23922 :         REGISTER_LONG_CONSTANT("SI_TKILL",   SI_TKILL,   CONST_CS | CONST_PERSISTENT);
     337             : #endif
     338             : 
     339             :         /* si_code for SIGCHILD */
     340             : #ifdef CLD_EXITED
     341       23922 :         REGISTER_LONG_CONSTANT("CLD_EXITED",    CLD_EXITED,    CONST_CS | CONST_PERSISTENT);
     342             : #endif
     343             : #ifdef CLD_KILLED
     344       23922 :         REGISTER_LONG_CONSTANT("CLD_KILLED",    CLD_KILLED,    CONST_CS | CONST_PERSISTENT);
     345             : #endif
     346             : #ifdef CLD_DUMPED
     347       23922 :         REGISTER_LONG_CONSTANT("CLD_DUMPED",    CLD_DUMPED,    CONST_CS | CONST_PERSISTENT);
     348             : #endif
     349             : #ifdef CLD_TRAPPED
     350       23922 :         REGISTER_LONG_CONSTANT("CLD_TRAPPED",   CLD_TRAPPED,   CONST_CS | CONST_PERSISTENT);
     351             : #endif
     352             : #ifdef CLD_STOPPED
     353       23922 :         REGISTER_LONG_CONSTANT("CLD_STOPPED",   CLD_STOPPED,   CONST_CS | CONST_PERSISTENT);
     354             : #endif
     355             : #ifdef CLD_CONTINUED
     356       23922 :         REGISTER_LONG_CONSTANT("CLD_CONTINUED", CLD_CONTINUED, CONST_CS | CONST_PERSISTENT);
     357             : #endif
     358             : 
     359             :         /* si_code for SIGTRAP */
     360             : #ifdef TRAP_BRKPT
     361       23922 :         REGISTER_LONG_CONSTANT("TRAP_BRKPT", TRAP_BRKPT, CONST_CS | CONST_PERSISTENT);
     362             : #endif
     363             : #ifdef TRAP_TRACE
     364       23922 :         REGISTER_LONG_CONSTANT("TRAP_TRACE", TRAP_TRACE, CONST_CS | CONST_PERSISTENT);
     365             : #endif
     366             : 
     367             :         /* si_code for SIGPOLL */
     368             : #ifdef POLL_IN
     369       23922 :         REGISTER_LONG_CONSTANT("POLL_IN",  POLL_IN,  CONST_CS | CONST_PERSISTENT);
     370             : #endif
     371             : #ifdef POLL_OUT
     372       23922 :         REGISTER_LONG_CONSTANT("POLL_OUT", POLL_OUT, CONST_CS | CONST_PERSISTENT);
     373             : #endif
     374             : #ifdef POLL_MSG
     375       23922 :         REGISTER_LONG_CONSTANT("POLL_MSG", POLL_MSG, CONST_CS | CONST_PERSISTENT);
     376             : #endif
     377             : #ifdef POLL_ERR
     378       23922 :         REGISTER_LONG_CONSTANT("POLL_ERR", POLL_ERR, CONST_CS | CONST_PERSISTENT);
     379             : #endif
     380             : #ifdef POLL_PRI
     381       23922 :         REGISTER_LONG_CONSTANT("POLL_PRI", POLL_PRI, CONST_CS | CONST_PERSISTENT);
     382             : #endif
     383             : #ifdef POLL_HUP
     384       23922 :         REGISTER_LONG_CONSTANT("POLL_HUP", POLL_HUP, CONST_CS | CONST_PERSISTENT);
     385             : #endif
     386             : 
     387             : #ifdef ILL_ILLOPC
     388       23922 :         REGISTER_LONG_CONSTANT("ILL_ILLOPC", ILL_ILLOPC, CONST_CS | CONST_PERSISTENT);
     389             : #endif
     390             : #ifdef ILL_ILLOPN
     391       23922 :         REGISTER_LONG_CONSTANT("ILL_ILLOPN", ILL_ILLOPN, CONST_CS | CONST_PERSISTENT);
     392             : #endif
     393             : #ifdef ILL_ILLADR
     394       23922 :         REGISTER_LONG_CONSTANT("ILL_ILLADR", ILL_ILLADR, CONST_CS | CONST_PERSISTENT);
     395             : #endif
     396             : #ifdef ILL_ILLTRP
     397       23922 :         REGISTER_LONG_CONSTANT("ILL_ILLTRP", ILL_ILLTRP, CONST_CS | CONST_PERSISTENT);
     398             : #endif
     399             : #ifdef ILL_PRVOPC
     400       23922 :         REGISTER_LONG_CONSTANT("ILL_PRVOPC", ILL_PRVOPC, CONST_CS | CONST_PERSISTENT);
     401             : #endif
     402             : #ifdef ILL_PRVREG
     403       23922 :         REGISTER_LONG_CONSTANT("ILL_PRVREG", ILL_PRVREG, CONST_CS | CONST_PERSISTENT);
     404             : #endif
     405             : #ifdef ILL_COPROC
     406       23922 :         REGISTER_LONG_CONSTANT("ILL_COPROC", ILL_COPROC, CONST_CS | CONST_PERSISTENT);
     407             : #endif
     408             : #ifdef ILL_BADSTK
     409       23922 :         REGISTER_LONG_CONSTANT("ILL_BADSTK", ILL_BADSTK, CONST_CS | CONST_PERSISTENT);
     410             : #endif
     411             : 
     412             : #ifdef FPE_INTDIV
     413       23922 :         REGISTER_LONG_CONSTANT("FPE_INTDIV", FPE_INTDIV, CONST_CS | CONST_PERSISTENT);
     414             : #endif
     415             : #ifdef FPE_INTOVF
     416       23922 :         REGISTER_LONG_CONSTANT("FPE_INTOVF", FPE_INTOVF, CONST_CS | CONST_PERSISTENT);
     417             : #endif
     418             : #ifdef FPE_FLTDIV
     419       23922 :         REGISTER_LONG_CONSTANT("FPE_FLTDIV", FPE_FLTDIV, CONST_CS | CONST_PERSISTENT);
     420             : #endif
     421             : #ifdef FPE_FLTOVF
     422       23922 :         REGISTER_LONG_CONSTANT("FPE_FLTOVF", FPE_FLTOVF, CONST_CS | CONST_PERSISTENT);
     423             : #endif
     424             : #ifdef FPE_FLTUND
     425       23922 :         REGISTER_LONG_CONSTANT("FPE_FLTUND", FPE_FLTINV, CONST_CS | CONST_PERSISTENT);
     426             : #endif
     427             : #ifdef FPE_FLTRES
     428       23922 :         REGISTER_LONG_CONSTANT("FPE_FLTRES", FPE_FLTRES, CONST_CS | CONST_PERSISTENT);
     429             : #endif
     430             : #ifdef FPE_FLTINV
     431       23922 :         REGISTER_LONG_CONSTANT("FPE_FLTINV", FPE_FLTINV, CONST_CS | CONST_PERSISTENT);
     432             : #endif
     433             : #ifdef FPE_FLTSUB
     434       23922 :         REGISTER_LONG_CONSTANT("FPE_FLTSUB", FPE_FLTSUB, CONST_CS | CONST_PERSISTENT);
     435             : #endif
     436             : 
     437             : #ifdef SEGV_MAPERR
     438       23922 :         REGISTER_LONG_CONSTANT("SEGV_MAPERR", SEGV_MAPERR, CONST_CS | CONST_PERSISTENT);
     439             : #endif
     440             : #ifdef SEGV_ACCERR
     441       23922 :         REGISTER_LONG_CONSTANT("SEGV_ACCERR", SEGV_ACCERR, CONST_CS | CONST_PERSISTENT);
     442             : #endif
     443             : 
     444             : #ifdef BUS_ADRALN
     445       23922 :         REGISTER_LONG_CONSTANT("BUS_ADRALN", BUS_ADRALN, CONST_CS | CONST_PERSISTENT);
     446             : #endif
     447             : #ifdef BUS_ADRERR
     448       23922 :         REGISTER_LONG_CONSTANT("BUS_ADRERR", BUS_ADRERR, CONST_CS | CONST_PERSISTENT);
     449             : #endif
     450             : #ifdef BUS_OBJERR
     451       23922 :         REGISTER_LONG_CONSTANT("BUS_OBJERR", BUS_OBJERR, CONST_CS | CONST_PERSISTENT);
     452             : #endif
     453             : #endif /* HAVE_SIGWAITINFO && HAVE_SIGTIMEDWAIT */
     454             :         /* }}} */
     455       23922 : }
     456             : 
     457       23922 : static void php_pcntl_register_errno_constants(INIT_FUNC_ARGS)
     458             : {
     459             : #ifdef EINTR
     460       23922 :         REGISTER_PCNTL_ERRNO_CONSTANT(EINTR);
     461             : #endif
     462             : #ifdef ECHILD
     463       23922 :         REGISTER_PCNTL_ERRNO_CONSTANT(ECHILD);
     464             : #endif
     465             : #ifdef EINVAL
     466       23922 :         REGISTER_PCNTL_ERRNO_CONSTANT(EINVAL);
     467             : #endif
     468             : #ifdef EAGAIN
     469       23922 :         REGISTER_PCNTL_ERRNO_CONSTANT(EAGAIN);
     470             : #endif
     471             : #ifdef ESRCH
     472       23922 :         REGISTER_PCNTL_ERRNO_CONSTANT(ESRCH);
     473             : #endif
     474             : #ifdef EACCES
     475       23922 :         REGISTER_PCNTL_ERRNO_CONSTANT(EACCES);
     476             : #endif
     477             : #ifdef EPERM
     478       23922 :         REGISTER_PCNTL_ERRNO_CONSTANT(EPERM);
     479             : #endif
     480             : #ifdef ENOMEM
     481       23922 :         REGISTER_PCNTL_ERRNO_CONSTANT(ENOMEM);
     482             : #endif
     483             : #ifdef E2BIG
     484       23922 :         REGISTER_PCNTL_ERRNO_CONSTANT(E2BIG);
     485             : #endif
     486             : #ifdef EFAULT
     487       23922 :         REGISTER_PCNTL_ERRNO_CONSTANT(EFAULT);
     488             : #endif
     489             : #ifdef EIO
     490       23922 :         REGISTER_PCNTL_ERRNO_CONSTANT(EIO);
     491             : #endif
     492             : #ifdef EISDIR
     493       23922 :         REGISTER_PCNTL_ERRNO_CONSTANT(EISDIR);
     494             : #endif
     495             : #ifdef ELIBBAD
     496       23922 :         REGISTER_PCNTL_ERRNO_CONSTANT(ELIBBAD);
     497             : #endif
     498             : #ifdef ELOOP
     499       23922 :         REGISTER_PCNTL_ERRNO_CONSTANT(ELOOP);
     500             : #endif
     501             : #ifdef EMFILE
     502       23922 :         REGISTER_PCNTL_ERRNO_CONSTANT(EMFILE);
     503             : #endif
     504             : #ifdef ENAMETOOLONG
     505       23922 :         REGISTER_PCNTL_ERRNO_CONSTANT(ENAMETOOLONG);
     506             : #endif
     507             : #ifdef ENFILE
     508       23922 :         REGISTER_PCNTL_ERRNO_CONSTANT(ENFILE);
     509             : #endif
     510             : #ifdef ENOENT
     511       23922 :         REGISTER_PCNTL_ERRNO_CONSTANT(ENOENT);
     512             : #endif
     513             : #ifdef ENOEXEC
     514       23922 :         REGISTER_PCNTL_ERRNO_CONSTANT(ENOEXEC);
     515             : #endif
     516             : #ifdef ENOTDIR
     517       23922 :         REGISTER_PCNTL_ERRNO_CONSTANT(ENOTDIR);
     518             : #endif
     519             : #ifdef ETXTBSY
     520       23922 :         REGISTER_PCNTL_ERRNO_CONSTANT(ETXTBSY);
     521             : #endif
     522       23922 : }
     523             : 
     524       23922 : static PHP_GINIT_FUNCTION(pcntl)
     525             : {
     526       23922 :         memset(pcntl_globals, 0, sizeof(*pcntl_globals));
     527       23922 : }
     528             : 
     529       23876 : PHP_RINIT_FUNCTION(pcntl)
     530             : {
     531       23876 :         zend_hash_init(&PCNTL_G(php_signal_table), 16, NULL, ZVAL_PTR_DTOR, 0);
     532       23876 :         PCNTL_G(head) = PCNTL_G(tail) = PCNTL_G(spares) = NULL;
     533       23876 :         PCNTL_G(async_signals) = 0;
     534       23876 :         return SUCCESS;
     535             : }
     536             : 
     537       23922 : PHP_MINIT_FUNCTION(pcntl)
     538             : {
     539       23922 :         php_register_signal_constants(INIT_FUNC_ARGS_PASSTHRU);
     540       23922 :         php_pcntl_register_errno_constants(INIT_FUNC_ARGS_PASSTHRU);
     541       23922 :         php_add_tick_function(pcntl_signal_dispatch, NULL);
     542       23922 :         orig_interrupt_function = zend_interrupt_function;
     543       23922 :         zend_interrupt_function = pcntl_interrupt_function;
     544             : 
     545       23922 :         return SUCCESS;
     546             : }
     547             : 
     548       23963 : PHP_MSHUTDOWN_FUNCTION(pcntl)
     549             : {
     550       23963 :         return SUCCESS;
     551             : }
     552             : 
     553       23919 : PHP_RSHUTDOWN_FUNCTION(pcntl)
     554             : {
     555             :         struct php_pcntl_pending_signal *sig;
     556             : 
     557             :         /* FIXME: if a signal is delivered after this point, things will go pear shaped;
     558             :          * need to remove signal handlers */
     559       23919 :         zend_hash_destroy(&PCNTL_G(php_signal_table));
     560       47839 :         while (PCNTL_G(head)) {
     561           1 :                 sig = PCNTL_G(head);
     562           1 :                 PCNTL_G(head) = sig->next;
     563             : #ifdef HAVE_STRUCT_SIGINFO_T
     564           1 :                 if (sig->siginfo) {
     565           1 :                         zend_array_destroy(sig->siginfo);
     566             :                 }
     567             : #endif
     568           1 :                 efree(sig);
     569             :         }
     570       48093 :         while (PCNTL_G(spares)) {
     571         255 :                 sig = PCNTL_G(spares);
     572         255 :                 PCNTL_G(spares) = sig->next;
     573         255 :                 efree(sig);
     574             :         }
     575       23919 :         return SUCCESS;
     576             : }
     577             : 
     578         150 : PHP_MINFO_FUNCTION(pcntl)
     579             : {
     580         150 :         php_info_print_table_start();
     581         150 :         php_info_print_table_header(2, "pcntl support", "enabled");
     582         150 :         php_info_print_table_end();
     583         150 : }
     584             : 
     585             : /* {{{ proto int pcntl_fork(void)
     586             :    Forks the currently running process following the same behavior as the UNIX fork() system call*/
     587          85 : PHP_FUNCTION(pcntl_fork)
     588             : {
     589             :         pid_t id;
     590             : 
     591          85 :         id = fork();
     592         133 :         if (id == -1) {
     593           0 :                 PCNTL_G(last_error) = errno;
     594           0 :                 php_error_docref(NULL, E_WARNING, "Error %d", errno);
     595             :         }
     596             : 
     597         133 :         RETURN_LONG((zend_long) id);
     598             : }
     599             : /* }}} */
     600             : 
     601             : /* {{{ proto int pcntl_alarm(int seconds)
     602             :    Set an alarm clock for delivery of a signal*/
     603          39 : PHP_FUNCTION(pcntl_alarm)
     604             : {
     605             :         zend_long seconds;
     606             : 
     607          39 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &seconds) == FAILURE)
     608           1 :                 return;
     609             : 
     610          38 :         RETURN_LONG ((zend_long) alarm(seconds));
     611             : }
     612             : /* }}} */
     613             : 
     614             : #define PHP_RUSAGE_PARA(from, to, field) \
     615             :         add_assoc_long(to, #field, from.field)
     616             : #if !defined(_OSD_POSIX) && !defined(__BEOS__) /* BS2000 has only a few fields in the rusage struct */
     617             :         #define PHP_RUSAGE_SPECIAL(from, to) \
     618             :                 PHP_RUSAGE_PARA(from, to, ru_oublock); \
     619             :                 PHP_RUSAGE_PARA(from, to, ru_inblock); \
     620             :                 PHP_RUSAGE_PARA(from, to, ru_msgsnd); \
     621             :                 PHP_RUSAGE_PARA(from, to, ru_msgrcv); \
     622             :                 PHP_RUSAGE_PARA(from, to, ru_maxrss); \
     623             :                 PHP_RUSAGE_PARA(from, to, ru_ixrss); \
     624             :                 PHP_RUSAGE_PARA(from, to, ru_idrss); \
     625             :                 PHP_RUSAGE_PARA(from, to, ru_minflt); \
     626             :                 PHP_RUSAGE_PARA(from, to, ru_majflt); \
     627             :                 PHP_RUSAGE_PARA(from, to, ru_nsignals); \
     628             :                 PHP_RUSAGE_PARA(from, to, ru_nvcsw); \
     629             :                 PHP_RUSAGE_PARA(from, to, ru_nivcsw); \
     630             :                 PHP_RUSAGE_PARA(from, to, ru_nswap);
     631             : #else /*_OSD_POSIX*/
     632             :         #define PHP_RUSAGE_SPECIAL(from, to)
     633             : #endif
     634             : 
     635             : #define PHP_RUSAGE_COMMON(from ,to) \
     636             :         PHP_RUSAGE_PARA(from, to, ru_utime.tv_usec); \
     637             :         PHP_RUSAGE_PARA(from, to, ru_utime.tv_sec); \
     638             :         PHP_RUSAGE_PARA(from, to, ru_stime.tv_usec); \
     639             :         PHP_RUSAGE_PARA(from, to, ru_stime.tv_sec);
     640             : 
     641             : #define PHP_RUSAGE_TO_ARRAY(from, to) \
     642             :         if (to) { \
     643             :                 PHP_RUSAGE_SPECIAL(from, to) \
     644             :                 PHP_RUSAGE_COMMON(from, to); \
     645             :         }
     646             : 
     647             : /* {{{ proto int pcntl_waitpid(int pid, int &status, int options, array &$rusage)
     648             :    Waits on or returns the status of a forked child as defined by the waitpid() system call */
     649          69 : PHP_FUNCTION(pcntl_waitpid)
     650             : {
     651          69 :         zend_long pid, options = 0;
     652          69 :         zval *z_status = NULL, *z_rusage = NULL;
     653             :         int status;
     654             :         pid_t child_id;
     655             : #ifdef HAVE_WAIT4
     656             :         struct rusage rusage;
     657             : #endif
     658             : 
     659          69 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "lz/|lz/", &pid, &z_status, &options, &z_rusage) == FAILURE) {
     660           1 :                 return;
     661             :         }
     662             : 
     663         136 :         status = zval_get_long(z_status);
     664             : 
     665             : #ifdef HAVE_WAIT4
     666          68 :         if (z_rusage) {
     667          10 :                 if (Z_TYPE_P(z_rusage) != IS_ARRAY) {
     668           4 :                         zval_dtor(z_rusage);
     669           4 :                         array_init(z_rusage);
     670             :                 } else {
     671           1 :                         zend_hash_clean(Z_ARRVAL_P(z_rusage));
     672             :                 }
     673             : 
     674           5 :                 memset(&rusage, 0, sizeof(struct rusage));
     675           5 :                 child_id = wait4((pid_t) pid, &status, options, &rusage);
     676             :         } else {
     677          63 :                 child_id = waitpid((pid_t) pid, &status, options);
     678             :         }
     679             : #else
     680             :         child_id = waitpid((pid_t) pid, &status, options);
     681             : #endif
     682             : 
     683          68 :         if (child_id < 0) {
     684           3 :                 PCNTL_G(last_error) = errno;
     685             :         }
     686             : 
     687             : #ifdef HAVE_WAIT4
     688          68 :         if (child_id > 0) {
     689          45 :                 PHP_RUSAGE_TO_ARRAY(rusage, z_rusage);
     690             :         }
     691             : #endif
     692             : 
     693          68 :         zval_dtor(z_status);
     694          68 :         ZVAL_LONG(z_status, status);
     695             : 
     696          68 :         RETURN_LONG((zend_long) child_id);
     697             : }
     698             : /* }}} */
     699             : 
     700             : /* {{{ proto int pcntl_wait(int &status, int $options, array &$rusage)
     701             :    Waits on or returns the status of a forked child as defined by the waitpid() system call */
     702          13 : PHP_FUNCTION(pcntl_wait)
     703             : {
     704          13 :         zend_long options = 0;
     705          13 :         zval *z_status = NULL, *z_rusage = NULL;
     706             :         int status;
     707             :         pid_t child_id;
     708             : #ifdef HAVE_WAIT3
     709             :         struct rusage rusage;
     710             : #endif
     711             : 
     712          13 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "z/|lz/", &z_status, &options, &z_rusage) == FAILURE) {
     713           1 :                 return;
     714             :         }
     715             : 
     716          24 :         status = zval_get_long(z_status);
     717             : #ifdef HAVE_WAIT3
     718          12 :         if (z_rusage) {
     719          10 :                 if (Z_TYPE_P(z_rusage) != IS_ARRAY) {
     720           4 :                         zval_dtor(z_rusage);
     721           4 :                         array_init(z_rusage);
     722             :                 } else {
     723           1 :                         zend_hash_clean(Z_ARRVAL_P(z_rusage));
     724             :                 }
     725             : 
     726           5 :                 memset(&rusage, 0, sizeof(struct rusage));
     727           5 :                 child_id = wait3(&status, options, &rusage);
     728           7 :         } else if (options) {
     729           2 :                 child_id = wait3(&status, options, NULL);
     730             :         } else {
     731           5 :                 child_id = wait(&status);
     732             :         }
     733             : #else
     734             :         child_id = wait(&status);
     735             : #endif
     736          12 :         if (child_id < 0) {
     737           5 :                 PCNTL_G(last_error) = errno;
     738             :         }
     739             : 
     740             : #ifdef HAVE_WAIT3
     741          12 :         if (child_id > 0) {
     742           7 :                 PHP_RUSAGE_TO_ARRAY(rusage, z_rusage);
     743             :         }
     744             : #endif
     745             : 
     746          12 :         zval_dtor(z_status);
     747          12 :         ZVAL_LONG(z_status, status);
     748             : 
     749          12 :         RETURN_LONG((zend_long) child_id);
     750             : }
     751             : /* }}} */
     752             : 
     753             : #undef PHP_RUSAGE_PARA
     754             : #undef PHP_RUSAGE_SPECIAL
     755             : #undef PHP_RUSAGE_COMMON
     756             : #undef PHP_RUSAGE_TO_ARRAY
     757             : 
     758             : /* {{{ proto bool pcntl_wifexited(int status) 
     759             :    Returns true if the child status code represents a successful exit */
     760           5 : PHP_FUNCTION(pcntl_wifexited)
     761             : {
     762             : #ifdef WIFEXITED
     763             :         zend_long status_word;
     764             : 
     765           5 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &status_word) == FAILURE) {
     766           1 :                return;
     767             :         }
     768             : 
     769           4 :         if (WIFEXITED(status_word))
     770           3 :                 RETURN_TRUE;
     771             : #endif
     772           1 :         RETURN_FALSE;
     773             : }
     774             : /* }}} */
     775             : 
     776             : /* {{{ proto bool pcntl_wifstopped(int status)
     777             :    Returns true if the child status code represents a stopped process (WUNTRACED must have been used with waitpid) */
     778           3 : PHP_FUNCTION(pcntl_wifstopped)
     779             : {
     780             : #ifdef WIFSTOPPED
     781             :         zend_long status_word;
     782             : 
     783           3 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &status_word) == FAILURE) {
     784           1 :                return;
     785             :         }
     786             : 
     787           2 :         if (WIFSTOPPED(status_word))
     788           1 :                 RETURN_TRUE;
     789             : #endif
     790           1 :         RETURN_FALSE;
     791             : }
     792             : /* }}} */
     793             : 
     794             : /* {{{ proto bool pcntl_wifsignaled(int status)
     795             :    Returns true if the child status code represents a process that was terminated due to a signal */
     796           3 : PHP_FUNCTION(pcntl_wifsignaled)
     797             : {
     798             : #ifdef WIFSIGNALED
     799             :         zend_long status_word;
     800             : 
     801           3 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &status_word) == FAILURE) {
     802           1 :                return;
     803             :         }
     804             : 
     805           2 :         if (WIFSIGNALED(status_word))
     806           1 :                 RETURN_TRUE;
     807             : #endif
     808           1 :         RETURN_FALSE;
     809             : }
     810             : /* }}} */
     811             : /* {{{ proto bool pcntl_wifcontinued(int status)
     812             :    Returns true if the child status code represents a process that was resumed due to a SIGCONT signal */
     813           0 : PHP_FUNCTION(pcntl_wifcontinued)
     814             : {
     815             : #ifdef HAVE_WCONTINUED
     816             :         zend_long status_word;
     817             : 
     818           0 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &status_word) == FAILURE) {
     819           0 :                return;
     820             :         }
     821             : 
     822           0 :         if (WIFCONTINUED(status_word))
     823           0 :                 RETURN_TRUE;
     824             : #endif
     825           0 :         RETURN_FALSE;
     826             : }
     827             : /* }}} */
     828             : 
     829             : 
     830             : /* {{{ proto int pcntl_wexitstatus(int status)
     831             :    Returns the status code of a child's exit */
     832           6 : PHP_FUNCTION(pcntl_wexitstatus)
     833             : {
     834             : #ifdef WEXITSTATUS
     835             :         zend_long status_word;
     836             : 
     837           6 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &status_word) == FAILURE) {
     838           1 :                return;
     839             :         }
     840             : 
     841           5 :         RETURN_LONG(WEXITSTATUS(status_word));
     842             : #else
     843             :         RETURN_FALSE;
     844             : #endif
     845             : }
     846             : /* }}} */
     847             : 
     848             : /* {{{ proto int pcntl_wtermsig(int status)
     849             :    Returns the number of the signal that terminated the process who's status code is passed  */
     850           2 : PHP_FUNCTION(pcntl_wtermsig)
     851             : {
     852             : #ifdef WTERMSIG
     853             :         zend_long status_word;
     854             : 
     855           2 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &status_word) == FAILURE) {
     856           1 :                return;
     857             :         }
     858             : 
     859           1 :         RETURN_LONG(WTERMSIG(status_word));
     860             : #else
     861             :         RETURN_FALSE;
     862             : #endif
     863             : }
     864             : /* }}} */
     865             : 
     866             : /* {{{ proto int pcntl_wstopsig(int status)
     867             :    Returns the number of the signal that caused the process to stop who's status code is passed */
     868           2 : PHP_FUNCTION(pcntl_wstopsig)
     869             : {
     870             : #ifdef WSTOPSIG
     871             :         zend_long status_word;
     872             : 
     873           2 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &status_word) == FAILURE) {
     874           1 :                return;
     875             :         }
     876             : 
     877           1 :         RETURN_LONG(WSTOPSIG(status_word));
     878             : #else
     879             :         RETURN_FALSE;
     880             : #endif
     881             : }
     882             : /* }}} */
     883             : 
     884             : /* {{{ proto bool pcntl_exec(string path [, array args [, array envs]])
     885             :    Executes specified program in current process space as defined by exec(2) */
     886           4 : PHP_FUNCTION(pcntl_exec)
     887             : {
     888           4 :         zval *args = NULL, *envs = NULL;
     889             :         zval *element;
     890             :         HashTable *args_hash, *envs_hash;
     891           4 :         int argc = 0, argi = 0;
     892           4 :         int envc = 0, envi = 0;
     893           4 :         char **argv = NULL, **envp = NULL;
     894             :         char **current_arg, **pair;
     895             :         int pair_length;
     896             :         zend_string *key;
     897             :         char *path;
     898             :         size_t path_len;
     899             :         zend_ulong key_num;
     900             : 
     901           4 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|aa", &path, &path_len, &args, &envs) == FAILURE) {
     902           1 :                 return;
     903             :         }
     904             : 
     905           3 :         if (ZEND_NUM_ARGS() > 1) {
     906             :                 /* Build argument list */
     907           3 :                 args_hash = Z_ARRVAL_P(args);
     908           3 :                 argc = zend_hash_num_elements(args_hash);
     909             : 
     910           3 :                 argv = safe_emalloc((argc + 2), sizeof(char *), 0);
     911           3 :                 *argv = path;
     912           3 :                 current_arg = argv+1;
     913          13 :                 ZEND_HASH_FOREACH_VAL(args_hash, element) {
     914           5 :                         if (argi >= argc) break;
     915           5 :                         convert_to_string_ex(element);
     916           5 :                         *current_arg = Z_STRVAL_P(element);
     917           5 :                         argi++;
     918           5 :                         current_arg++;
     919             :                 } ZEND_HASH_FOREACH_END();
     920           3 :                 *(current_arg) = NULL;
     921             :         } else {
     922           0 :                 argv = emalloc(2 * sizeof(char *));
     923           0 :                 *argv = path;
     924           0 :                 *(argv+1) = NULL;
     925             :         }
     926             : 
     927           3 :         if ( ZEND_NUM_ARGS() == 3 ) {
     928             :                 /* Build environment pair list */
     929           2 :                 envs_hash = Z_ARRVAL_P(envs);
     930           2 :                 envc = zend_hash_num_elements(envs_hash);
     931             : 
     932           2 :                 pair = envp = safe_emalloc((envc + 1), sizeof(char *), 0);
     933          10 :                 ZEND_HASH_FOREACH_KEY_VAL(envs_hash, key_num, key, element) {
     934           4 :                         if (envi >= envc) break;
     935           4 :                         if (!key) {
     936           1 :                                 key = zend_long_to_str(key_num);
     937             :                         } else {
     938             :                                 zend_string_addref(key);
     939             :                         }
     940             : 
     941           4 :                         convert_to_string_ex(element);
     942             : 
     943             :                         /* Length of element + equal sign + length of key + null */
     944           4 :                         pair_length = Z_STRLEN_P(element) + ZSTR_LEN(key) + 2;
     945           4 :                         *pair = emalloc(pair_length);
     946           4 :                         strlcpy(*pair, ZSTR_VAL(key), ZSTR_LEN(key) + 1);
     947           4 :                         strlcat(*pair, "=", pair_length);
     948           4 :                         strlcat(*pair, Z_STRVAL_P(element), pair_length);
     949             : 
     950             :                         /* Cleanup */
     951             :                         zend_string_release(key);
     952           4 :                         envi++;
     953           4 :                         pair++;
     954             :                 } ZEND_HASH_FOREACH_END();
     955           2 :                 *(pair) = NULL;
     956             : 
     957           2 :                 if (execve(path, argv, envp) == -1) {
     958           1 :                         PCNTL_G(last_error) = errno;
     959           1 :                         php_error_docref(NULL, E_WARNING, "Error has occurred: (errno %d) %s", errno, strerror(errno));
     960             :                 }
     961             : 
     962             :                 /* Cleanup */
     963           1 :                 for (pair = envp; *pair != NULL; pair++) efree(*pair);
     964           1 :                 efree(envp);
     965             :         } else {
     966             : 
     967           1 :                 if (execv(path, argv) == -1) {
     968           0 :                         PCNTL_G(last_error) = errno;
     969           0 :                         php_error_docref(NULL, E_WARNING, "Error has occurred: (errno %d) %s", errno, strerror(errno));
     970             :                 }
     971             :         }
     972             : 
     973           2 :         efree(argv);
     974             : 
     975           1 :         RETURN_FALSE;
     976             : }
     977             : /* }}} */
     978             : 
     979             : /* {{{ proto bool pcntl_signal(int signo, callback handle [, bool restart_syscalls])
     980             :    Assigns a system signal handler to a PHP function */
     981          16 : PHP_FUNCTION(pcntl_signal)
     982             : {
     983             :         zval *handle;
     984             :         zend_string *func_name;
     985             :         zend_long signo;
     986          16 :         zend_bool restart_syscalls = 1;
     987             : 
     988          16 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "lz|b", &signo, &handle, &restart_syscalls) == FAILURE) {
     989           1 :                 return;
     990             :         }
     991             : 
     992          15 :         if (signo < 1 || signo > 32) {
     993           2 :                 php_error_docref(NULL, E_WARNING, "Invalid signal");
     994           2 :                 RETURN_FALSE;
     995             :         }
     996             : 
     997          13 :         if (!PCNTL_G(spares)) {
     998             :                 /* since calling malloc() from within a signal handler is not portable,
     999             :                  * pre-allocate a few records for recording signals */
    1000             :                 int i;
    1001         264 :                 for (i = 0; i < 32; i++) {
    1002             :                         struct php_pcntl_pending_signal *psig;
    1003             : 
    1004         256 :                         psig = emalloc(sizeof(*psig));
    1005         256 :                         psig->next = PCNTL_G(spares);
    1006         256 :                         PCNTL_G(spares) = psig;
    1007             :                 }
    1008             :         }
    1009             : 
    1010             :         /* Special long value case for SIG_DFL and SIG_IGN */
    1011          26 :         if (Z_TYPE_P(handle) == IS_LONG) {
    1012           4 :                 if (Z_LVAL_P(handle) != (zend_long) SIG_DFL && Z_LVAL_P(handle) != (zend_long) SIG_IGN) {
    1013           0 :                         php_error_docref(NULL, E_WARNING, "Invalid value for handle argument specified");
    1014           0 :                         RETURN_FALSE;
    1015             :                 }
    1016           4 :                 if (php_signal(signo, (Sigfunc *) Z_LVAL_P(handle), (int) restart_syscalls) == (Sigfunc *)SIG_ERR) {
    1017           0 :                         PCNTL_G(last_error) = errno;
    1018           0 :                         php_error_docref(NULL, E_WARNING, "Error assigning signal");
    1019           0 :                         RETURN_FALSE;
    1020             :                 }
    1021           4 :                 zend_hash_index_update(&PCNTL_G(php_signal_table), signo, handle);
    1022           4 :                 RETURN_TRUE;
    1023             :         }
    1024             : 
    1025           9 :         if (!zend_is_callable(handle, 0, &func_name)) {
    1026           1 :                 PCNTL_G(last_error) = EINVAL;
    1027           1 :                 php_error_docref(NULL, E_WARNING, "%s is not a callable function name error", ZSTR_VAL(func_name));
    1028           1 :                 zend_string_release(func_name);
    1029           1 :                 RETURN_FALSE;
    1030             :         }
    1031           8 :         zend_string_release(func_name);
    1032             : 
    1033             :         /* Add the function name to our signal table */
    1034           8 :         if (zend_hash_index_update(&PCNTL_G(php_signal_table), signo, handle)) {
    1035           8 :                 if (Z_REFCOUNTED_P(handle)) Z_ADDREF_P(handle);
    1036             :         }
    1037             : 
    1038           8 :         if (php_signal4(signo, pcntl_signal_handler, (int) restart_syscalls, 1) == (Sigfunc *)SIG_ERR) {
    1039           0 :                 PCNTL_G(last_error) = errno;
    1040           0 :                 php_error_docref(NULL, E_WARNING, "Error assigning signal");
    1041           0 :                 RETURN_FALSE;
    1042             :         }
    1043           8 :         RETURN_TRUE;
    1044             : }
    1045             : /* }}} */
    1046             : 
    1047             : /* {{{ proto bool pcntl_signal_get_handler(int signo)
    1048             :    Gets signal handler */
    1049           4 : PHP_FUNCTION(pcntl_signal_get_handler)
    1050             : {
    1051             :         zval *prev_handle;
    1052             :         zend_long signo;
    1053             : 
    1054           4 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &signo) == FAILURE) {
    1055           0 :                 return;
    1056             :         }
    1057             : 
    1058           4 :         if (signo < 1 || signo > 32) {
    1059           0 :                 php_error_docref(NULL, E_WARNING, "Invalid signal");
    1060           0 :                 RETURN_FALSE;
    1061             :         }
    1062             : 
    1063           4 :         if ((prev_handle = zend_hash_index_find(&PCNTL_G(php_signal_table), signo)) != NULL) {
    1064           6 :                 RETURN_ZVAL(prev_handle, 1, 0);
    1065             :         } else {
    1066           1 :                 RETURN_LONG((zend_long)SIG_DFL);
    1067             :         }
    1068             : }
    1069             : 
    1070             : /* {{{ proto bool pcntl_signal_dispatch()
    1071             :    Dispatch signals to signal handlers */
    1072           4 : PHP_FUNCTION(pcntl_signal_dispatch)
    1073             : {
    1074           4 :         pcntl_signal_dispatch();
    1075           4 :         RETURN_TRUE;
    1076             : }
    1077             : /* }}} */
    1078             : 
    1079             : #ifdef HAVE_SIGPROCMASK
    1080             : /* {{{ proto bool pcntl_sigprocmask(int how, array set[, array &oldset])
    1081             :    Examine and change blocked signals */
    1082           9 : PHP_FUNCTION(pcntl_sigprocmask)
    1083             : {
    1084             :         zend_long          how, signo;
    1085           9 :         zval         *user_set, *user_oldset = NULL, *user_signo;
    1086             :         sigset_t      set, oldset;
    1087             : 
    1088           9 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "la|z/", &how, &user_set, &user_oldset) == FAILURE) {
    1089           0 :                 return;
    1090             :         }
    1091             : 
    1092           9 :         if (sigemptyset(&set) != 0 || sigemptyset(&oldset) != 0) {
    1093           0 :                 PCNTL_G(last_error) = errno;
    1094           0 :                 php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
    1095           0 :                 RETURN_FALSE;
    1096             :         }
    1097             : 
    1098          24 :         ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(user_set), user_signo) {
    1099           8 :                 signo = zval_get_long(user_signo);
    1100           8 :                 if (sigaddset(&set, signo) != 0) {
    1101           1 :                         PCNTL_G(last_error) = errno;
    1102           1 :                         php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
    1103           1 :                         RETURN_FALSE;
    1104             :                 }
    1105             :         } ZEND_HASH_FOREACH_END();
    1106             : 
    1107           8 :         if (sigprocmask(how, &set, &oldset) != 0) {
    1108           0 :                 PCNTL_G(last_error) = errno;
    1109           0 :                 php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
    1110           0 :                 RETURN_FALSE;
    1111             :         }
    1112             : 
    1113           8 :         if (user_oldset != NULL) {
    1114          14 :                 if (Z_TYPE_P(user_oldset) != IS_ARRAY) {
    1115           1 :                         zval_dtor(user_oldset);
    1116           1 :                         array_init(user_oldset);
    1117             :                 } else {
    1118           6 :                         zend_hash_clean(Z_ARRVAL_P(user_oldset));
    1119             :                 }
    1120         448 :                 for (signo = 1; signo < MAX(NSIG-1, SIGRTMAX); ++signo) {
    1121         441 :                         if (sigismember(&oldset, signo) != 1) {
    1122         431 :                                 continue;
    1123             :                         }
    1124          10 :                         add_next_index_long(user_oldset, signo);
    1125             :                 }
    1126             :         }
    1127             : 
    1128           8 :         RETURN_TRUE;
    1129             : }
    1130             : /* }}} */
    1131             : #endif
    1132             : 
    1133             : #ifdef HAVE_STRUCT_SIGINFO_T
    1134             : # if HAVE_SIGWAITINFO && HAVE_SIGTIMEDWAIT
    1135           5 : static void pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAMETERS, int timedwait) /* {{{ */
    1136             : {
    1137           5 :         zval            *user_set, *user_signo, *user_siginfo = NULL;
    1138           5 :         zend_long             tv_sec = 0, tv_nsec = 0;
    1139             :         sigset_t         set;
    1140             :         int              signo;
    1141             :         siginfo_t        siginfo;
    1142             :         struct timespec  timeout;
    1143             : 
    1144           5 :         if (timedwait) {
    1145           2 :                 if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|z/ll", &user_set, &user_siginfo, &tv_sec, &tv_nsec) == FAILURE) {
    1146           0 :                         return;
    1147             :                 }
    1148             :         } else {
    1149           3 :                 if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|z/", &user_set, &user_siginfo) == FAILURE) {
    1150           0 :                         return;
    1151             :                 }
    1152             :         }
    1153             : 
    1154           5 :         if (sigemptyset(&set) != 0) {
    1155           0 :                 PCNTL_G(last_error) = errno;
    1156           0 :                 php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
    1157           0 :                 RETURN_FALSE;
    1158             :         }
    1159             : 
    1160          14 :         ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(user_set), user_signo) {
    1161           5 :                 signo = zval_get_long(user_signo);
    1162           5 :                 if (sigaddset(&set, signo) != 0) {
    1163           1 :                         PCNTL_G(last_error) = errno;
    1164           1 :                         php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
    1165           1 :                         RETURN_FALSE;
    1166             :                 }
    1167             :         } ZEND_HASH_FOREACH_END();
    1168             : 
    1169           4 :         if (timedwait) {
    1170           2 :                 timeout.tv_sec  = (time_t) tv_sec;
    1171           2 :                 timeout.tv_nsec = tv_nsec;
    1172           2 :                 signo = sigtimedwait(&set, &siginfo, &timeout);
    1173             :         } else {
    1174           2 :                 signo = sigwaitinfo(&set, &siginfo);
    1175             :         }
    1176           4 :         if (signo == -1 && errno != EAGAIN) {
    1177           1 :                 PCNTL_G(last_error) = errno;
    1178           1 :                 php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
    1179             :         }
    1180             : 
    1181             :         /*
    1182             :          * sigtimedwait and sigwaitinfo can return 0 on success on some
    1183             :          * platforms, e.g. NetBSD
    1184             :          */
    1185           4 :         if (!signo && siginfo.si_signo) {
    1186           0 :                 signo = siginfo.si_signo;
    1187             :         }
    1188           4 :         pcntl_siginfo_to_zval(signo, &siginfo, user_siginfo);
    1189           4 :         RETURN_LONG(signo);
    1190             : }
    1191             : /* }}} */
    1192             : 
    1193             : /* {{{ proto int pcnlt_sigwaitinfo(array set[, array &siginfo])
    1194             :    Synchronously wait for queued signals */
    1195           3 : PHP_FUNCTION(pcntl_sigwaitinfo)
    1196             : {
    1197           3 :         pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
    1198           3 : }
    1199             : /* }}} */
    1200             : 
    1201             : /* {{{ proto int pcntl_sigtimedwait(array set[, array &siginfo[, int seconds[, int nanoseconds]]])
    1202             :    Wait for queued signals */
    1203           2 : PHP_FUNCTION(pcntl_sigtimedwait)
    1204             : {
    1205           2 :         pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
    1206           2 : }
    1207             : /* }}} */
    1208             : # endif
    1209             : 
    1210          10 : static void pcntl_siginfo_to_zval(int signo, siginfo_t *siginfo, zval *user_siginfo) /* {{{ */
    1211             : {
    1212          10 :         if (signo > 0 && user_siginfo) {
    1213           9 :                 if (Z_TYPE_P(user_siginfo) != IS_ARRAY) {
    1214             :                         zval_dtor(user_siginfo);
    1215           1 :                         array_init(user_siginfo);
    1216             :                 } else {
    1217           8 :                         zend_hash_clean(Z_ARRVAL_P(user_siginfo));
    1218             :                 }
    1219           9 :                 add_assoc_long_ex(user_siginfo, "signo", sizeof("signo")-1, siginfo->si_signo);
    1220           9 :                 add_assoc_long_ex(user_siginfo, "errno", sizeof("errno")-1, siginfo->si_errno);
    1221           9 :                 add_assoc_long_ex(user_siginfo, "code",  sizeof("code")-1,  siginfo->si_code);
    1222           9 :                 switch(signo) {
    1223             : #ifdef SIGCHLD
    1224             :                         case SIGCHLD:
    1225           1 :                                 add_assoc_long_ex(user_siginfo,   "status", sizeof("status")-1, siginfo->si_status);
    1226             : # ifdef si_utime
    1227           1 :                                 add_assoc_double_ex(user_siginfo, "utime",  sizeof("utime")-1,  siginfo->si_utime);
    1228             : # endif
    1229             : # ifdef si_stime
    1230           1 :                                 add_assoc_double_ex(user_siginfo, "stime",  sizeof("stime")-1,  siginfo->si_stime);
    1231             : # endif
    1232           1 :                                 add_assoc_long_ex(user_siginfo,   "pid",    sizeof("pid")-1,    siginfo->si_pid);
    1233           1 :                                 add_assoc_long_ex(user_siginfo,   "uid",    sizeof("uid")-1,    siginfo->si_uid);
    1234           1 :                                 break;
    1235             :                         case SIGUSR1:
    1236             :                         case SIGUSR2:
    1237           1 :                                 add_assoc_long_ex(user_siginfo,   "pid",    sizeof("pid")-1,    siginfo->si_pid);
    1238           1 :                                 add_assoc_long_ex(user_siginfo,   "uid",    sizeof("uid")-1,    siginfo->si_uid);
    1239           1 :                                 break;
    1240             : #endif
    1241             :                         case SIGILL:
    1242             :                         case SIGFPE:
    1243             :                         case SIGSEGV:
    1244             :                         case SIGBUS:
    1245           0 :                                 add_assoc_double_ex(user_siginfo, "addr", sizeof("addr")-1, (zend_long)siginfo->si_addr);
    1246           0 :                                 break;
    1247             : #ifdef SIGPOLL
    1248             :                         case SIGPOLL:
    1249           0 :                                 add_assoc_long_ex(user_siginfo, "band", sizeof("band")-1, siginfo->si_band);
    1250             : # ifdef si_fd
    1251           0 :                                 add_assoc_long_ex(user_siginfo, "fd",   sizeof("fd")-1,   siginfo->si_fd);
    1252             : # endif
    1253             :                                 break;
    1254             : #endif
    1255             :                 }
    1256             :         }
    1257          10 : }
    1258             : /* }}} */
    1259             : #endif
    1260             : 
    1261             : #ifdef HAVE_GETPRIORITY
    1262             : /* {{{ proto int pcntl_getpriority([int pid [, int process_identifier]])
    1263             :    Get the priority of any process */
    1264           0 : PHP_FUNCTION(pcntl_getpriority)
    1265             : {
    1266           0 :         zend_long who = PRIO_PROCESS;
    1267           0 :         zend_long pid = getpid();
    1268             :         int pri;
    1269             : 
    1270           0 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ll", &pid, &who) == FAILURE) {
    1271           0 :                 RETURN_FALSE;
    1272             :         }
    1273             : 
    1274             :         /* needs to be cleared, since any returned value is valid */
    1275           0 :         errno = 0;
    1276             : 
    1277           0 :         pri = getpriority(who, pid);
    1278             : 
    1279           0 :         if (errno) {
    1280           0 :                 PCNTL_G(last_error) = errno;
    1281           0 :                 switch (errno) {
    1282             :                         case ESRCH:
    1283           0 :                                 php_error_docref(NULL, E_WARNING, "Error %d: No process was located using the given parameters", errno);
    1284           0 :                                 break;
    1285             :                         case EINVAL:
    1286           0 :                                 php_error_docref(NULL, E_WARNING, "Error %d: Invalid identifier flag", errno);
    1287           0 :                                 break;
    1288             :                         default:
    1289           0 :                                 php_error_docref(NULL, E_WARNING, "Unknown error %d has occurred", errno);
    1290             :                                 break;
    1291             :                 }
    1292           0 :                 RETURN_FALSE;
    1293             :         }
    1294             : 
    1295           0 :         RETURN_LONG(pri);
    1296             : }
    1297             : /* }}} */
    1298             : #endif
    1299             : 
    1300             : #ifdef HAVE_SETPRIORITY
    1301             : /* {{{ proto bool pcntl_setpriority(int priority [, int pid [, int process_identifier]])
    1302             :    Change the priority of any process */
    1303           0 : PHP_FUNCTION(pcntl_setpriority)
    1304             : {
    1305           0 :         zend_long who = PRIO_PROCESS;
    1306           0 :         zend_long pid = getpid();
    1307             :         zend_long pri;
    1308             : 
    1309           0 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|ll", &pri, &pid, &who) == FAILURE) {
    1310           0 :                 RETURN_FALSE;
    1311             :         }
    1312             : 
    1313           0 :         if (setpriority(who, pid, pri)) {
    1314           0 :                 PCNTL_G(last_error) = errno;
    1315           0 :                 switch (errno) {
    1316             :                         case ESRCH:
    1317           0 :                                 php_error_docref(NULL, E_WARNING, "Error %d: No process was located using the given parameters", errno);
    1318           0 :                                 break;
    1319             :                         case EINVAL:
    1320           0 :                                 php_error_docref(NULL, E_WARNING, "Error %d: Invalid identifier flag", errno);
    1321           0 :                                 break;
    1322             :                         case EPERM:
    1323           0 :                                 php_error_docref(NULL, E_WARNING, "Error %d: A process was located, but neither its effective nor real user ID matched the effective user ID of the caller", errno);
    1324           0 :                                 break;
    1325             :                         case EACCES:
    1326           0 :                                 php_error_docref(NULL, E_WARNING, "Error %d: Only a super user may attempt to increase the process priority", errno);
    1327           0 :                                 break;
    1328             :                         default:
    1329           0 :                                 php_error_docref(NULL, E_WARNING, "Unknown error %d has occurred", errno);
    1330             :                                 break;
    1331             :                 }
    1332           0 :                 RETURN_FALSE;
    1333             :         }
    1334             : 
    1335           0 :         RETURN_TRUE;
    1336             : }
    1337             : /* }}} */
    1338             : #endif
    1339             : 
    1340             : /* {{{ proto int pcntl_get_last_error(void)
    1341             :    Retrieve the error number set by the last pcntl function which failed. */
    1342           2 : PHP_FUNCTION(pcntl_get_last_error)
    1343             : {
    1344           2 :         RETURN_LONG(PCNTL_G(last_error));
    1345             : }
    1346             : /* }}} */
    1347             : 
    1348             : /* {{{ proto string pcntl_strerror(int errno)
    1349             :    Retrieve the system error message associated with the given errno. */
    1350           0 : PHP_FUNCTION(pcntl_strerror)
    1351             : {
    1352             :         zend_long error;
    1353             : 
    1354           0 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &error) == FAILURE) {
    1355           0 :                 RETURN_FALSE;
    1356             :         }
    1357             : 
    1358           0 :         RETURN_STRING(strerror(error));
    1359             : }
    1360             : /* }}} */
    1361             : 
    1362             : /* Our custom signal handler that calls the appropriate php_function */
    1363             : #ifdef HAVE_STRUCT_SIGINFO_T
    1364           6 : static void pcntl_signal_handler(int signo, siginfo_t *siginfo, void *context)
    1365             : #else
    1366             : static void pcntl_signal_handler(int signo)
    1367             : #endif
    1368             : {
    1369             :         struct php_pcntl_pending_signal *psig;
    1370             : 
    1371           6 :         psig = PCNTL_G(spares);
    1372           6 :         if (!psig) {
    1373             :                 /* oops, too many signals for us to track, so we'll forget about this one */
    1374           0 :                 return;
    1375             :         }
    1376           6 :         PCNTL_G(spares) = psig->next;
    1377             : 
    1378           6 :         psig->signo = signo;
    1379           6 :         psig->next = NULL;
    1380             : 
    1381             : #ifdef HAVE_STRUCT_SIGINFO_T
    1382             :         zval user_siginfo;
    1383           6 :         array_init(&user_siginfo);
    1384           6 :         pcntl_siginfo_to_zval(signo, siginfo, &user_siginfo);
    1385           6 :         psig->siginfo = zend_array_dup(Z_ARRVAL(user_siginfo));
    1386           6 :         zval_ptr_dtor(&user_siginfo);
    1387             : #endif
    1388             : 
    1389             :         /* the head check is important, as the tick handler cannot atomically clear both
    1390             :          * the head and tail */
    1391           6 :         if (PCNTL_G(head) && PCNTL_G(tail)) {
    1392           0 :                 PCNTL_G(tail)->next = psig;
    1393             :         } else {
    1394           6 :                 PCNTL_G(head) = psig;
    1395             :         }
    1396           6 :         PCNTL_G(tail) = psig;
    1397           6 :         PCNTL_G(pending_signals) = 1;
    1398           6 :         if (PCNTL_G(async_signals)) {
    1399           1 :                 EG(vm_interrupt) = 1;
    1400             :         }
    1401             : }
    1402             : 
    1403          40 : void pcntl_signal_dispatch()
    1404             : {
    1405             :         zval params[2], *handle, retval;
    1406             :         struct php_pcntl_pending_signal *queue, *next;
    1407             :         sigset_t mask;
    1408             :         sigset_t old_mask;
    1409             : 
    1410          40 :         if(!PCNTL_G(pending_signals)) {
    1411          34 :                 return;
    1412             :         }
    1413             : 
    1414             :         /* Mask all signals */
    1415           6 :         sigfillset(&mask);
    1416           6 :         sigprocmask(SIG_BLOCK, &mask, &old_mask);
    1417             : 
    1418             :         /* Bail if the queue is empty or if we are already playing the queue */
    1419           6 :         if (!PCNTL_G(head) || PCNTL_G(processing_signal_queue)) {
    1420           1 :                 sigprocmask(SIG_SETMASK, &old_mask, NULL);
    1421           1 :                 return;
    1422             :         }
    1423             : 
    1424             :         /* Prevent reentrant handler calls */
    1425           5 :         PCNTL_G(processing_signal_queue) = 1;
    1426             : 
    1427           5 :         queue = PCNTL_G(head);
    1428           5 :         PCNTL_G(head) = NULL; /* simple stores are atomic */
    1429             : 
    1430             :         /* Allocate */
    1431             : 
    1432          15 :         while (queue) {
    1433           5 :                 if ((handle = zend_hash_index_find(&PCNTL_G(php_signal_table), queue->signo)) != NULL) {
    1434           5 :                         if (Z_TYPE_P(handle) != IS_LONG) {
    1435           5 :                                 ZVAL_NULL(&retval);
    1436           5 :                                 ZVAL_LONG(&params[0], queue->signo);
    1437             : #ifdef HAVE_STRUCT_SIGINFO_T
    1438           5 :                                 ZVAL_ARR(&params[1], queue->siginfo);
    1439             : #else
    1440             :                                 ZVAL_NULL(&params[1]);
    1441             : #endif
    1442             : 
    1443             :                                 /* Call php signal handler - Note that we do not report errors, and we ignore the return value */
    1444             :                                 /* FIXME: this is probably broken when multiple signals are handled in this while loop (retval) */
    1445           5 :                                 call_user_function(EG(function_table), NULL, handle, &retval, 2, params);
    1446           5 :                                 zval_ptr_dtor(&retval);
    1447           5 :                                 zval_ptr_dtor(&params[0]);
    1448           5 :                                 zval_ptr_dtor(&params[1]);
    1449             :                         }
    1450             :                 }
    1451             : 
    1452           5 :                 next = queue->next;
    1453           5 :                 queue->next = PCNTL_G(spares);
    1454           5 :                 PCNTL_G(spares) = queue;
    1455           5 :                 queue = next;
    1456             :         }
    1457             : 
    1458           5 :         PCNTL_G(pending_signals) = 0;
    1459             : 
    1460             :         /* Re-enable queue */
    1461           5 :         PCNTL_G(processing_signal_queue) = 0;
    1462             : 
    1463             :         /* return signal mask to previous state */
    1464           5 :         sigprocmask(SIG_SETMASK, &old_mask, NULL);
    1465             : }
    1466             : 
    1467             : /* {{{ proto bool pcntl_async_signals([bool on[)
    1468             :    Enable/disable asynchronous signal handling and return the old setting. */
    1469           1 : PHP_FUNCTION(pcntl_async_signals)
    1470             : {
    1471             :         zend_bool on;
    1472             : 
    1473           1 :         if (ZEND_NUM_ARGS() == 0) {
    1474           0 :                 RETURN_BOOL(PCNTL_G(async_signals));
    1475             :         }
    1476           1 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &on) == FAILURE) {
    1477           0 :                 return;
    1478             :         }
    1479           1 :         RETVAL_BOOL(PCNTL_G(async_signals));
    1480           1 :         PCNTL_G(async_signals) = on;
    1481             : }
    1482             : /* }}} */
    1483             : 
    1484           1 : static void pcntl_interrupt_function(zend_execute_data *execute_data)
    1485             : {
    1486           1 :         pcntl_signal_dispatch();
    1487           1 :         if (orig_interrupt_function) {
    1488           0 :                 orig_interrupt_function(execute_data);
    1489             :         }
    1490           1 : }
    1491             : 
    1492             : /*
    1493             :  * Local variables:
    1494             :  * tab-width: 4
    1495             :  * c-basic-offset: 4
    1496             :  * indent-tabs-mode: t
    1497             :  * End:
    1498             :  */

Generated by: LCOV version 1.10

Generated at Sun, 18 Sep 2016 08:20:12 +0000 (8 days ago)

Copyright © 2005-2016 The PHP Group
All rights reserved.