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: 410 490 83.7 %
Date: 2015-05-21 Functions: 28 32 87.5 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Thu, 21 May 2015 19:59:00 +0000 (2 days ago)

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