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: 446 546 81.7 %
Date: 2022-01-21 Functions: 32 36 88.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Fri, 21 Jan 2022 14:15:17 +0000 (30 hours ago)

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