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

Generated by: LCOV version 1.10

Generated at Wed, 20 Jul 2016 02:56:23 +0000 (4 days ago)

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