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: 387 461 83.9 %
Date: 2014-12-13 Functions: 28 31 90.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sat, 13 Dec 2014 06:16:17 +0000 (6 days ago)

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