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: 386 460 83.9 %
Date: 2014-11-22 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       20507 : void php_register_signal_constants(INIT_FUNC_ARGS)
     203             : {
     204             : 
     205             :         /* Wait Constants */
     206             : #ifdef WNOHANG
     207       20507 :         REGISTER_LONG_CONSTANT("WNOHANG",  (zend_long) WNOHANG, CONST_CS | CONST_PERSISTENT);
     208             : #endif
     209             : #ifdef WUNTRACED
     210       20507 :         REGISTER_LONG_CONSTANT("WUNTRACED",  (zend_long) WUNTRACED, CONST_CS | CONST_PERSISTENT);
     211             : #endif
     212             : 
     213             :         /* Signal Constants */
     214       20507 :         REGISTER_LONG_CONSTANT("SIG_IGN",  (zend_long) SIG_IGN, CONST_CS | CONST_PERSISTENT);
     215       20507 :         REGISTER_LONG_CONSTANT("SIG_DFL",  (zend_long) SIG_DFL, CONST_CS | CONST_PERSISTENT);
     216       20507 :         REGISTER_LONG_CONSTANT("SIG_ERR",  (zend_long) SIG_ERR, CONST_CS | CONST_PERSISTENT);
     217       20507 :         REGISTER_LONG_CONSTANT("SIGHUP",   (zend_long) SIGHUP,  CONST_CS | CONST_PERSISTENT);
     218       20507 :         REGISTER_LONG_CONSTANT("SIGINT",   (zend_long) SIGINT,  CONST_CS | CONST_PERSISTENT);
     219       20507 :         REGISTER_LONG_CONSTANT("SIGQUIT",  (zend_long) SIGQUIT, CONST_CS | CONST_PERSISTENT);
     220       20507 :         REGISTER_LONG_CONSTANT("SIGILL",   (zend_long) SIGILL,  CONST_CS | CONST_PERSISTENT);
     221       20507 :         REGISTER_LONG_CONSTANT("SIGTRAP",  (zend_long) SIGTRAP, CONST_CS | CONST_PERSISTENT);
     222       20507 :         REGISTER_LONG_CONSTANT("SIGABRT",  (zend_long) SIGABRT, CONST_CS | CONST_PERSISTENT);
     223             : #ifdef SIGIOT
     224       20507 :         REGISTER_LONG_CONSTANT("SIGIOT",   (zend_long) SIGIOT,  CONST_CS | CONST_PERSISTENT);
     225             : #endif
     226       20507 :         REGISTER_LONG_CONSTANT("SIGBUS",   (zend_long) SIGBUS,  CONST_CS | CONST_PERSISTENT);
     227       20507 :         REGISTER_LONG_CONSTANT("SIGFPE",   (zend_long) SIGFPE,  CONST_CS | CONST_PERSISTENT);
     228       20507 :         REGISTER_LONG_CONSTANT("SIGKILL",  (zend_long) SIGKILL, CONST_CS | CONST_PERSISTENT);
     229       20507 :         REGISTER_LONG_CONSTANT("SIGUSR1",  (zend_long) SIGUSR1, CONST_CS | CONST_PERSISTENT);
     230       20507 :         REGISTER_LONG_CONSTANT("SIGSEGV",  (zend_long) SIGSEGV, CONST_CS | CONST_PERSISTENT);
     231       20507 :         REGISTER_LONG_CONSTANT("SIGUSR2",  (zend_long) SIGUSR2, CONST_CS | CONST_PERSISTENT);
     232       20507 :         REGISTER_LONG_CONSTANT("SIGPIPE",  (zend_long) SIGPIPE, CONST_CS | CONST_PERSISTENT);
     233       20507 :         REGISTER_LONG_CONSTANT("SIGALRM",  (zend_long) SIGALRM, CONST_CS | CONST_PERSISTENT);
     234       20507 :         REGISTER_LONG_CONSTANT("SIGTERM",  (zend_long) SIGTERM, CONST_CS | CONST_PERSISTENT);
     235             : #ifdef SIGSTKFLT
     236       20507 :         REGISTER_LONG_CONSTANT("SIGSTKFLT",(zend_long) SIGSTKFLT, CONST_CS | CONST_PERSISTENT);
     237             : #endif 
     238             : #ifdef SIGCLD
     239       20507 :         REGISTER_LONG_CONSTANT("SIGCLD",   (zend_long) SIGCLD, CONST_CS | CONST_PERSISTENT);
     240             : #endif
     241             : #ifdef SIGCHLD
     242       20507 :         REGISTER_LONG_CONSTANT("SIGCHLD",  (zend_long) SIGCHLD, CONST_CS | CONST_PERSISTENT);
     243             : #endif
     244       20507 :         REGISTER_LONG_CONSTANT("SIGCONT",  (zend_long) SIGCONT, CONST_CS | CONST_PERSISTENT);
     245       20507 :         REGISTER_LONG_CONSTANT("SIGSTOP",  (zend_long) SIGSTOP, CONST_CS | CONST_PERSISTENT);
     246       20507 :         REGISTER_LONG_CONSTANT("SIGTSTP",  (zend_long) SIGTSTP, CONST_CS | CONST_PERSISTENT);
     247       20507 :         REGISTER_LONG_CONSTANT("SIGTTIN",  (zend_long) SIGTTIN, CONST_CS | CONST_PERSISTENT);
     248       20507 :         REGISTER_LONG_CONSTANT("SIGTTOU",  (zend_long) SIGTTOU, CONST_CS | CONST_PERSISTENT);
     249       20507 :         REGISTER_LONG_CONSTANT("SIGURG",   (zend_long) SIGURG , CONST_CS | CONST_PERSISTENT);
     250       20507 :         REGISTER_LONG_CONSTANT("SIGXCPU",  (zend_long) SIGXCPU, CONST_CS | CONST_PERSISTENT);
     251       20507 :         REGISTER_LONG_CONSTANT("SIGXFSZ",  (zend_long) SIGXFSZ, CONST_CS | CONST_PERSISTENT);
     252       20507 :         REGISTER_LONG_CONSTANT("SIGVTALRM",(zend_long) SIGVTALRM, CONST_CS | CONST_PERSISTENT);
     253       20507 :         REGISTER_LONG_CONSTANT("SIGPROF",  (zend_long) SIGPROF, CONST_CS | CONST_PERSISTENT);
     254       20507 :         REGISTER_LONG_CONSTANT("SIGWINCH", (zend_long) SIGWINCH, CONST_CS | CONST_PERSISTENT);
     255             : #ifdef SIGPOLL
     256       20507 :         REGISTER_LONG_CONSTANT("SIGPOLL",  (zend_long) SIGPOLL, CONST_CS | CONST_PERSISTENT);
     257             : #endif
     258       20507 :         REGISTER_LONG_CONSTANT("SIGIO",    (zend_long) SIGIO, CONST_CS | CONST_PERSISTENT);
     259             : #ifdef SIGPWR
     260       20507 :         REGISTER_LONG_CONSTANT("SIGPWR",   (zend_long) SIGPWR, CONST_CS | CONST_PERSISTENT);
     261             : #endif
     262             : #ifdef SIGSYS
     263       20507 :         REGISTER_LONG_CONSTANT("SIGSYS",   (zend_long) SIGSYS, CONST_CS | CONST_PERSISTENT);
     264       20507 :         REGISTER_LONG_CONSTANT("SIGBABY",  (zend_long) SIGSYS, CONST_CS | CONST_PERSISTENT);
     265             : #endif
     266             : 
     267             : #if HAVE_GETPRIORITY || HAVE_SETPRIORITY
     268       20507 :         REGISTER_LONG_CONSTANT("PRIO_PGRP", PRIO_PGRP, CONST_CS | CONST_PERSISTENT);
     269       20507 :         REGISTER_LONG_CONSTANT("PRIO_USER", PRIO_USER, CONST_CS | CONST_PERSISTENT);
     270       20507 :         REGISTER_LONG_CONSTANT("PRIO_PROCESS", PRIO_PROCESS, CONST_CS | CONST_PERSISTENT);
     271             : #endif
     272             : 
     273             :         /* {{{ "how" argument for sigprocmask */
     274             : #ifdef HAVE_SIGPROCMASK
     275       20507 :         REGISTER_LONG_CONSTANT("SIG_BLOCK",   SIG_BLOCK, CONST_CS | CONST_PERSISTENT);
     276       20507 :         REGISTER_LONG_CONSTANT("SIG_UNBLOCK", SIG_UNBLOCK, CONST_CS | CONST_PERSISTENT);
     277       20507 :         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       20507 :         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       20507 :         REGISTER_LONG_CONSTANT("SI_KERNEL",  SI_KERNEL,  CONST_CS | CONST_PERSISTENT);
     289             : #endif
     290       20507 :         REGISTER_LONG_CONSTANT("SI_QUEUE",   SI_QUEUE,   CONST_CS | CONST_PERSISTENT);
     291       20507 :         REGISTER_LONG_CONSTANT("SI_TIMER",   SI_TIMER,   CONST_CS | CONST_PERSISTENT);
     292       20507 :         REGISTER_LONG_CONSTANT("SI_MESGQ",   SI_MESGQ,   CONST_CS | CONST_PERSISTENT);
     293       20507 :         REGISTER_LONG_CONSTANT("SI_ASYNCIO", SI_ASYNCIO, CONST_CS | CONST_PERSISTENT);
     294             : #ifdef SI_SIGIO
     295       20507 :         REGISTER_LONG_CONSTANT("SI_SIGIO",   SI_SIGIO,   CONST_CS | CONST_PERSISTENT);
     296             : #endif
     297             : #ifdef SI_TKILL
     298       20507 :         REGISTER_LONG_CONSTANT("SI_TKILL",   SI_TKILL,   CONST_CS | CONST_PERSISTENT);
     299             : #endif
     300             : 
     301             :         /* si_code for SIGCHILD */
     302             : #ifdef CLD_EXITED
     303       20507 :         REGISTER_LONG_CONSTANT("CLD_EXITED",    CLD_EXITED,    CONST_CS | CONST_PERSISTENT);
     304             : #endif
     305             : #ifdef CLD_KILLED
     306       20507 :         REGISTER_LONG_CONSTANT("CLD_KILLED",    CLD_KILLED,    CONST_CS | CONST_PERSISTENT);
     307             : #endif
     308             : #ifdef CLD_DUMPED
     309       20507 :         REGISTER_LONG_CONSTANT("CLD_DUMPED",    CLD_DUMPED,    CONST_CS | CONST_PERSISTENT);
     310             : #endif
     311             : #ifdef CLD_TRAPPED
     312       20507 :         REGISTER_LONG_CONSTANT("CLD_TRAPPED",   CLD_TRAPPED,   CONST_CS | CONST_PERSISTENT);
     313             : #endif
     314             : #ifdef CLD_STOPPED
     315       20507 :         REGISTER_LONG_CONSTANT("CLD_STOPPED",   CLD_STOPPED,   CONST_CS | CONST_PERSISTENT);
     316             : #endif
     317             : #ifdef CLD_CONTINUED
     318       20507 :         REGISTER_LONG_CONSTANT("CLD_CONTINUED", CLD_CONTINUED, CONST_CS | CONST_PERSISTENT);
     319             : #endif
     320             : 
     321             :         /* si_code for SIGTRAP */
     322             : #ifdef TRAP_BRKPT
     323       20507 :         REGISTER_LONG_CONSTANT("TRAP_BRKPT", TRAP_BRKPT, CONST_CS | CONST_PERSISTENT);
     324             : #endif
     325             : #ifdef TRAP_TRACE
     326       20507 :         REGISTER_LONG_CONSTANT("TRAP_TRACE", TRAP_TRACE, CONST_CS | CONST_PERSISTENT);
     327             : #endif
     328             : 
     329             :         /* si_code for SIGPOLL */
     330             : #ifdef POLL_IN
     331       20507 :         REGISTER_LONG_CONSTANT("POLL_IN",  POLL_IN,  CONST_CS | CONST_PERSISTENT);
     332             : #endif
     333             : #ifdef POLL_OUT
     334       20507 :         REGISTER_LONG_CONSTANT("POLL_OUT", POLL_OUT, CONST_CS | CONST_PERSISTENT);
     335             : #endif
     336             : #ifdef POLL_MSG
     337       20507 :         REGISTER_LONG_CONSTANT("POLL_MSG", POLL_MSG, CONST_CS | CONST_PERSISTENT);
     338             : #endif
     339             : #ifdef POLL_ERR
     340       20507 :         REGISTER_LONG_CONSTANT("POLL_ERR", POLL_ERR, CONST_CS | CONST_PERSISTENT);
     341             : #endif
     342             : #ifdef POLL_PRI
     343       20507 :         REGISTER_LONG_CONSTANT("POLL_PRI", POLL_PRI, CONST_CS | CONST_PERSISTENT);
     344             : #endif
     345             : #ifdef POLL_HUP
     346       20507 :         REGISTER_LONG_CONSTANT("POLL_HUP", POLL_HUP, CONST_CS | CONST_PERSISTENT);
     347             : #endif
     348             : 
     349             : #ifdef ILL_ILLOPC
     350       20507 :         REGISTER_LONG_CONSTANT("ILL_ILLOPC", ILL_ILLOPC, CONST_CS | CONST_PERSISTENT);
     351             : #endif
     352             : #ifdef ILL_ILLOPN
     353       20507 :         REGISTER_LONG_CONSTANT("ILL_ILLOPN", ILL_ILLOPN, CONST_CS | CONST_PERSISTENT);
     354             : #endif
     355             : #ifdef ILL_ILLADR
     356       20507 :         REGISTER_LONG_CONSTANT("ILL_ILLADR", ILL_ILLADR, CONST_CS | CONST_PERSISTENT);
     357             : #endif
     358             : #ifdef ILL_ILLTRP
     359       20507 :         REGISTER_LONG_CONSTANT("ILL_ILLTRP", ILL_ILLTRP, CONST_CS | CONST_PERSISTENT);
     360             : #endif
     361             : #ifdef ILL_PRVOPC
     362       20507 :         REGISTER_LONG_CONSTANT("ILL_PRVOPC", ILL_PRVOPC, CONST_CS | CONST_PERSISTENT);
     363             : #endif
     364             : #ifdef ILL_PRVREG
     365       20507 :         REGISTER_LONG_CONSTANT("ILL_PRVREG", ILL_PRVREG, CONST_CS | CONST_PERSISTENT);
     366             : #endif
     367             : #ifdef ILL_COPROC
     368       20507 :         REGISTER_LONG_CONSTANT("ILL_COPROC", ILL_COPROC, CONST_CS | CONST_PERSISTENT);
     369             : #endif
     370             : #ifdef ILL_BADSTK
     371       20507 :         REGISTER_LONG_CONSTANT("ILL_BADSTK", ILL_BADSTK, CONST_CS | CONST_PERSISTENT);
     372             : #endif
     373             : 
     374             : #ifdef FPE_INTDIV
     375       20507 :         REGISTER_LONG_CONSTANT("FPE_INTDIV", FPE_INTDIV, CONST_CS | CONST_PERSISTENT);
     376             : #endif
     377             : #ifdef FPE_INTOVF
     378       20507 :         REGISTER_LONG_CONSTANT("FPE_INTOVF", FPE_INTOVF, CONST_CS | CONST_PERSISTENT);
     379             : #endif
     380             : #ifdef FPE_FLTDIV
     381       20507 :         REGISTER_LONG_CONSTANT("FPE_FLTDIV", FPE_FLTDIV, CONST_CS | CONST_PERSISTENT);
     382             : #endif
     383             : #ifdef FPE_FLTOVF
     384       20507 :         REGISTER_LONG_CONSTANT("FPE_FLTOVF", FPE_FLTOVF, CONST_CS | CONST_PERSISTENT);
     385             : #endif
     386             : #ifdef FPE_FLTUND
     387       20507 :         REGISTER_LONG_CONSTANT("FPE_FLTUND", FPE_FLTINV, CONST_CS | CONST_PERSISTENT);
     388             : #endif
     389             : #ifdef FPE_FLTRES
     390       20507 :         REGISTER_LONG_CONSTANT("FPE_FLTRES", FPE_FLTRES, CONST_CS | CONST_PERSISTENT);
     391             : #endif
     392             : #ifdef FPE_FLTINV
     393       20507 :         REGISTER_LONG_CONSTANT("FPE_FLTINV", FPE_FLTINV, CONST_CS | CONST_PERSISTENT);
     394             : #endif
     395             : #ifdef FPE_FLTSUB
     396       20507 :         REGISTER_LONG_CONSTANT("FPE_FLTSUB", FPE_FLTSUB, CONST_CS | CONST_PERSISTENT);
     397             : #endif
     398             : 
     399             : #ifdef SEGV_MAPERR
     400       20507 :         REGISTER_LONG_CONSTANT("SEGV_MAPERR", SEGV_MAPERR, CONST_CS | CONST_PERSISTENT);
     401             : #endif
     402             : #ifdef SEGV_ACCERR
     403       20507 :         REGISTER_LONG_CONSTANT("SEGV_ACCERR", SEGV_ACCERR, CONST_CS | CONST_PERSISTENT);
     404             : #endif
     405             : 
     406             : #ifdef BUS_ADRALN
     407       20507 :         REGISTER_LONG_CONSTANT("BUS_ADRALN", BUS_ADRALN, CONST_CS | CONST_PERSISTENT);
     408             : #endif
     409             : #ifdef BUS_ADRERR
     410       20507 :         REGISTER_LONG_CONSTANT("BUS_ADRERR", BUS_ADRERR, CONST_CS | CONST_PERSISTENT);
     411             : #endif
     412             : #ifdef BUS_OBJERR
     413       20507 :         REGISTER_LONG_CONSTANT("BUS_OBJERR", BUS_OBJERR, CONST_CS | CONST_PERSISTENT);
     414             : #endif
     415             : #endif /* HAVE_SIGWAITINFO && HAVE_SIGTIMEDWAIT */
     416             :         /* }}} */
     417       20507 : }
     418             : 
     419       20507 : static void php_pcntl_register_errno_constants(INIT_FUNC_ARGS)
     420             : {
     421             : #ifdef EINTR
     422       20507 :         REGISTER_PCNTL_ERRNO_CONSTANT(EINTR);
     423             : #endif
     424             : #ifdef ECHILD
     425       20507 :         REGISTER_PCNTL_ERRNO_CONSTANT(ECHILD);
     426             : #endif
     427             : #ifdef EINVAL
     428       20507 :         REGISTER_PCNTL_ERRNO_CONSTANT(EINVAL);
     429             : #endif
     430             : #ifdef EAGAIN
     431       20507 :         REGISTER_PCNTL_ERRNO_CONSTANT(EAGAIN);
     432             : #endif
     433             : #ifdef ESRCH
     434       20507 :         REGISTER_PCNTL_ERRNO_CONSTANT(ESRCH);
     435             : #endif
     436             : #ifdef EACCES
     437       20507 :         REGISTER_PCNTL_ERRNO_CONSTANT(EACCES);
     438             : #endif
     439             : #ifdef EPERM
     440       20507 :         REGISTER_PCNTL_ERRNO_CONSTANT(EPERM);
     441             : #endif
     442             : #ifdef ENOMEM
     443       20507 :         REGISTER_PCNTL_ERRNO_CONSTANT(ENOMEM);
     444             : #endif
     445             : #ifdef E2BIG
     446       20507 :         REGISTER_PCNTL_ERRNO_CONSTANT(E2BIG);
     447             : #endif
     448             : #ifdef EFAULT
     449       20507 :         REGISTER_PCNTL_ERRNO_CONSTANT(EFAULT);
     450             : #endif
     451             : #ifdef EIO
     452       20507 :         REGISTER_PCNTL_ERRNO_CONSTANT(EIO);
     453             : #endif
     454             : #ifdef EISDIR
     455       20507 :         REGISTER_PCNTL_ERRNO_CONSTANT(EISDIR);
     456             : #endif
     457             : #ifdef ELIBBAD
     458       20507 :         REGISTER_PCNTL_ERRNO_CONSTANT(ELIBBAD);
     459             : #endif
     460             : #ifdef ELOOP
     461       20507 :         REGISTER_PCNTL_ERRNO_CONSTANT(ELOOP);
     462             : #endif
     463             : #ifdef EMFILE
     464       20507 :         REGISTER_PCNTL_ERRNO_CONSTANT(EMFILE);
     465             : #endif
     466             : #ifdef ENAMETOOLONG
     467       20507 :         REGISTER_PCNTL_ERRNO_CONSTANT(ENAMETOOLONG);
     468             : #endif
     469             : #ifdef ENFILE
     470       20507 :         REGISTER_PCNTL_ERRNO_CONSTANT(ENFILE);
     471             : #endif
     472             : #ifdef ENOENT
     473       20507 :         REGISTER_PCNTL_ERRNO_CONSTANT(ENOENT);
     474             : #endif
     475             : #ifdef ENOEXEC
     476       20507 :         REGISTER_PCNTL_ERRNO_CONSTANT(ENOEXEC);
     477             : #endif
     478             : #ifdef ENOTDIR
     479       20507 :         REGISTER_PCNTL_ERRNO_CONSTANT(ENOTDIR);
     480             : #endif
     481             : #ifdef ETXTBSY
     482       20507 :         REGISTER_PCNTL_ERRNO_CONSTANT(ETXTBSY);
     483             : #endif
     484       20507 : }
     485             : 
     486       20507 : static PHP_GINIT_FUNCTION(pcntl)
     487             : { 
     488       20507 :         memset(pcntl_globals, 0, sizeof(*pcntl_globals));
     489       20507 : }
     490             : 
     491       20464 : PHP_RINIT_FUNCTION(pcntl)
     492             : {
     493       20464 :         zend_hash_init(&PCNTL_G(php_signal_table), 16, NULL, ZVAL_PTR_DTOR, 0);
     494       20464 :         PCNTL_G(head) = PCNTL_G(tail) = PCNTL_G(spares) = NULL;
     495       20464 :         return SUCCESS;
     496             : }
     497             : 
     498       20507 : PHP_MINIT_FUNCTION(pcntl)
     499             : {
     500       20507 :         php_register_signal_constants(INIT_FUNC_ARGS_PASSTHRU);
     501       20507 :         php_pcntl_register_errno_constants(INIT_FUNC_ARGS_PASSTHRU);
     502       20507 :         php_add_tick_function(pcntl_signal_dispatch TSRMLS_CC);
     503             : 
     504       20507 :         return SUCCESS;
     505             : }
     506             : 
     507       20541 : PHP_MSHUTDOWN_FUNCTION(pcntl)
     508             : {
     509       20541 :         return SUCCESS;
     510             : }
     511             : 
     512       20500 : 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       20500 :         zend_hash_destroy(&PCNTL_G(php_signal_table));
     519       41001 :         while (PCNTL_G(head)) {
     520           1 :                 sig = PCNTL_G(head);
     521           1 :                 PCNTL_G(head) = sig->next;
     522           1 :                 efree(sig);
     523             :         }
     524       41191 :         while (PCNTL_G(spares)) {
     525         191 :                 sig = PCNTL_G(spares);
     526         191 :                 PCNTL_G(spares) = sig->next;
     527         191 :                 efree(sig);
     528             :         }
     529       20500 :         return SUCCESS;
     530             : }
     531             : 
     532         143 : PHP_MINFO_FUNCTION(pcntl)
     533             : {
     534         143 :         php_info_print_table_start();
     535         143 :         php_info_print_table_header(2, "pcntl support", "enabled");
     536         143 :         php_info_print_table_end();
     537         143 : }
     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          68 : PHP_FUNCTION(pcntl_waitpid)
     571             : {
     572          68 :         zend_long pid, options = 0;
     573          68 :         zval *z_status = NULL;
     574             :         int status;
     575             :         pid_t child_id;
     576             : 
     577          68 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz/|l", &pid, &z_status, &options) == FAILURE)
     578           1 :                 return;
     579             :         
     580         134 :         convert_to_long_ex(z_status);
     581             : 
     582          67 :         status = Z_LVAL_P(z_status);
     583             : 
     584          67 :         child_id = waitpid((pid_t) pid, &status, options);
     585             : 
     586          67 :         if (child_id < 0) {
     587           1 :                 PCNTL_G(last_error) = errno;
     588             :         }
     589             : 
     590          67 :         Z_LVAL_P(z_status) = status;
     591             : 
     592          67 :         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 :                 RETURN_TRUE;
     877             :         }
     878             :         
     879           6 :         if (!zend_is_callable(handle, 0, &func_name TSRMLS_CC)) {
     880           1 :                 PCNTL_G(last_error) = EINVAL;
     881           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s is not a callable function name error", func_name->val);
     882           1 :                 zend_string_release(func_name);
     883           1 :                 RETURN_FALSE;
     884             :         }
     885           5 :         zend_string_release(func_name);
     886             :         
     887             :         /* Add the function name to our signal table */
     888           5 :         if (zend_hash_index_update(&PCNTL_G(php_signal_table), signo, handle)) {
     889           5 :                 if (Z_REFCOUNTED_P(handle)) Z_ADDREF_P(handle);
     890             :         }
     891             :         
     892           5 :         if (php_signal4(signo, pcntl_signal_handler, (int) restart_syscalls, 1) == SIG_ERR) {
     893           0 :                 PCNTL_G(last_error) = errno;
     894           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error assigning signal");
     895           0 :                 RETURN_FALSE;
     896             :         }
     897           5 :         RETURN_TRUE;
     898             : }
     899             : /* }}} */
     900             : 
     901             : /* {{{ proto bool pcntl_signal_dispatch()
     902             :    Dispatch signals to signal handlers */
     903           2 : PHP_FUNCTION(pcntl_signal_dispatch)
     904             : {
     905           2 :         pcntl_signal_dispatch();
     906           2 :         RETURN_TRUE;
     907             : }
     908             : /* }}} */
     909             : 
     910             : #ifdef HAVE_SIGPROCMASK
     911             : /* {{{ proto bool pcntl_sigprocmask(int how, array set[, array &oldset])
     912             :    Examine and change blocked signals */
     913           9 : PHP_FUNCTION(pcntl_sigprocmask)
     914             : {
     915             :         zend_long          how, signo;
     916           9 :         zval         *user_set, *user_oldset = NULL, *user_signo;
     917             :         sigset_t      set, oldset;
     918             : 
     919           9 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "la|z/", &how, &user_set, &user_oldset) == FAILURE) {
     920           0 :                 return;
     921             :         }
     922             : 
     923           9 :         if (sigemptyset(&set) != 0 || sigemptyset(&oldset) != 0) {
     924           0 :                 PCNTL_G(last_error) = errno;
     925           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
     926           0 :                 RETURN_FALSE;
     927             :         }
     928             : 
     929          24 :         ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(user_set), user_signo) {
     930           8 :                 if (Z_TYPE_P(user_signo) != IS_LONG) {
     931           2 :                         SEPARATE_ZVAL(user_signo);
     932           2 :                         convert_to_long_ex(user_signo);
     933             :                 }
     934           8 :                 signo = Z_LVAL_P(user_signo);
     935           8 :                 if (sigaddset(&set, signo) != 0) {
     936           1 :                         PCNTL_G(last_error) = errno;
     937           1 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
     938           1 :                         RETURN_FALSE;
     939             :                 }
     940             :         } ZEND_HASH_FOREACH_END();
     941             : 
     942           8 :         if (sigprocmask(how, &set, &oldset) != 0) {
     943           0 :                 PCNTL_G(last_error) = errno;
     944           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
     945           0 :                 RETURN_FALSE;
     946             :         }
     947             : 
     948           8 :         if (user_oldset != NULL) {
     949          14 :                 if (Z_TYPE_P(user_oldset) != IS_ARRAY) {
     950           1 :                         zval_dtor(user_oldset);
     951           1 :                         array_init(user_oldset);
     952             :                 } else {
     953           6 :                         zend_hash_clean(Z_ARRVAL_P(user_oldset));
     954             :                 }
     955         448 :                 for (signo = 1; signo < MAX(NSIG-1, SIGRTMAX); ++signo) {
     956         441 :                         if (sigismember(&oldset, signo) != 1) {
     957         431 :                                 continue;
     958             :                         }
     959          10 :                         add_next_index_long(user_oldset, signo);
     960             :                 }
     961             :         }
     962             : 
     963           8 :         RETURN_TRUE;
     964             : }
     965             : /* }}} */
     966             : #endif
     967             : 
     968             : #if HAVE_SIGWAITINFO && HAVE_SIGTIMEDWAIT
     969           5 : static void pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAMETERS, int timedwait) /* {{{ */
     970             : {
     971           5 :         zval            *user_set, *user_signo, *user_siginfo = NULL;
     972           5 :         zend_long             tv_sec = 0, tv_nsec = 0;
     973             :         sigset_t         set;
     974             :         int              signo;
     975             :         siginfo_t        siginfo;
     976             :         struct timespec  timeout;
     977             : 
     978           5 :         if (timedwait) {
     979           2 :                 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z/ll", &user_set, &user_siginfo, &tv_sec, &tv_nsec) == FAILURE) {
     980           0 :                         return;
     981             :                 }
     982             :         } else {
     983           3 :                 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z/", &user_set, &user_siginfo) == FAILURE) {
     984           0 :                         return;
     985             :                 }
     986             :         }
     987             : 
     988           5 :         if (sigemptyset(&set) != 0) {
     989           0 :                 PCNTL_G(last_error) = errno;
     990           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
     991           0 :                 RETURN_FALSE;
     992             :         }
     993             : 
     994          14 :         ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(user_set), user_signo) {
     995           5 :                 if (Z_TYPE_P(user_signo) != IS_LONG) {
     996           2 :                         SEPARATE_ZVAL(user_signo);
     997           2 :                         convert_to_long_ex(user_signo);
     998             :                 }
     999           5 :                 signo = Z_LVAL_P(user_signo);
    1000           5 :                 if (sigaddset(&set, signo) != 0) {
    1001           1 :                         PCNTL_G(last_error) = errno;
    1002           1 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
    1003           1 :                         RETURN_FALSE;
    1004             :                 }
    1005             :         } ZEND_HASH_FOREACH_END();
    1006             : 
    1007           4 :         if (timedwait) {
    1008           2 :                 timeout.tv_sec  = (time_t) tv_sec;
    1009           2 :                 timeout.tv_nsec = tv_nsec;
    1010           2 :                 signo = sigtimedwait(&set, &siginfo, &timeout);
    1011             :         } else {
    1012           2 :                 signo = sigwaitinfo(&set, &siginfo);
    1013             :         }
    1014           4 :         if (signo == -1 && errno != EAGAIN) {
    1015           1 :                 PCNTL_G(last_error) = errno;
    1016           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
    1017             :         }
    1018             : 
    1019             :         /*
    1020             :          * sigtimedwait and sigwaitinfo can return 0 on success on some 
    1021             :          * platforms, e.g. NetBSD
    1022             :          */
    1023           4 :         if (!signo && siginfo.si_signo) {
    1024           0 :                 signo = siginfo.si_signo;
    1025             :         }
    1026             : 
    1027           4 :         if (signo > 0 && user_siginfo) {
    1028           6 :                 if (Z_TYPE_P(user_siginfo) != IS_ARRAY) {
    1029           1 :                         zval_dtor(user_siginfo);
    1030           1 :                         array_init(user_siginfo);
    1031             :                 } else {
    1032           2 :                         zend_hash_clean(Z_ARRVAL_P(user_siginfo));
    1033             :                 }
    1034           3 :                 add_assoc_long_ex(user_siginfo, "signo", sizeof("signo")-1, siginfo.si_signo);
    1035           3 :                 add_assoc_long_ex(user_siginfo, "errno", sizeof("errno")-1, siginfo.si_errno);
    1036           3 :                 add_assoc_long_ex(user_siginfo, "code",  sizeof("code")-1,  siginfo.si_code);
    1037           3 :                 switch(signo) {
    1038             : #ifdef SIGCHLD
    1039             :                         case SIGCHLD:
    1040           1 :                                 add_assoc_long_ex(user_siginfo,   "status", sizeof("status")-1, siginfo.si_status);
    1041             : # ifdef si_utime
    1042           1 :                                 add_assoc_double_ex(user_siginfo, "utime",  sizeof("utime")-1,  siginfo.si_utime);
    1043             : # endif
    1044             : # ifdef si_stime
    1045           1 :                                 add_assoc_double_ex(user_siginfo, "stime",  sizeof("stime")-1,  siginfo.si_stime);
    1046             : # endif
    1047           1 :                                 add_assoc_long_ex(user_siginfo,   "pid",    sizeof("pid")-1,    siginfo.si_pid);
    1048           1 :                                 add_assoc_long_ex(user_siginfo,   "uid",    sizeof("uid")-1,    siginfo.si_uid);
    1049           1 :                                 break;
    1050             : #endif
    1051             :                         case SIGILL:
    1052             :                         case SIGFPE:
    1053             :                         case SIGSEGV:
    1054             :                         case SIGBUS:
    1055           0 :                                 add_assoc_double_ex(user_siginfo, "addr", sizeof("addr")-1, (zend_long)siginfo.si_addr);
    1056           0 :                                 break;
    1057             : #ifdef SIGPOLL
    1058             :                         case SIGPOLL:
    1059           0 :                                 add_assoc_long_ex(user_siginfo, "band", sizeof("band")-1, siginfo.si_band);
    1060             : # ifdef si_fd
    1061           0 :                                 add_assoc_long_ex(user_siginfo, "fd",   sizeof("fd")-1,   siginfo.si_fd);
    1062             : # endif
    1063             :                                 break;
    1064             : #endif
    1065             :                 }
    1066             :         }
    1067             :         
    1068           4 :         RETURN_LONG(signo);
    1069             : }
    1070             : /* }}} */
    1071             : 
    1072             : /* {{{ proto int pcnlt_sigwaitinfo(array set[, array &siginfo])
    1073             :    Synchronously wait for queued signals */
    1074           3 : PHP_FUNCTION(pcntl_sigwaitinfo)
    1075             : {
    1076           3 :         pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
    1077           3 : }
    1078             : /* }}} */
    1079             : 
    1080             : /* {{{ proto int pcntl_sigtimedwait(array set[, array &siginfo[, int seconds[, int nanoseconds]]])
    1081             :    Wait for queued signals */
    1082           2 : PHP_FUNCTION(pcntl_sigtimedwait)
    1083             : {
    1084           2 :         pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
    1085           2 : }
    1086             : /* }}} */
    1087             : #endif
    1088             : 
    1089             : #ifdef HAVE_GETPRIORITY
    1090             : /* {{{ proto int pcntl_getpriority([int pid [, int process_identifier]])
    1091             :    Get the priority of any process */
    1092           0 : PHP_FUNCTION(pcntl_getpriority)
    1093             : {
    1094           0 :         zend_long who = PRIO_PROCESS;
    1095           0 :         zend_long pid = getpid();
    1096             :         int pri;
    1097             :         
    1098           0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ll", &pid, &who) == FAILURE) {
    1099           0 :                 RETURN_FALSE;
    1100             :         }
    1101             : 
    1102             :         /* needs to be cleared, since any returned value is valid */ 
    1103           0 :         errno = 0;
    1104             : 
    1105           0 :         pri = getpriority(who, pid);
    1106             : 
    1107           0 :         if (errno) {
    1108           0 :                 PCNTL_G(last_error) = errno;
    1109           0 :                 switch (errno) {
    1110             :                         case ESRCH:
    1111           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: No process was located using the given parameters", errno);
    1112           0 :                                 break;
    1113             :                         case EINVAL:
    1114           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: Invalid identifier flag", errno);
    1115           0 :                                 break;
    1116             :                         default:
    1117           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error %d has occurred", errno);
    1118             :                                 break;
    1119             :                 }
    1120           0 :                 RETURN_FALSE;
    1121             :         }
    1122             : 
    1123           0 :         RETURN_LONG(pri);
    1124             : }
    1125             : /* }}} */
    1126             : #endif
    1127             : 
    1128             : #ifdef HAVE_SETPRIORITY
    1129             : /* {{{ proto bool pcntl_setpriority(int priority [, int pid [, int process_identifier]])
    1130             :    Change the priority of any process */
    1131           0 : PHP_FUNCTION(pcntl_setpriority)
    1132             : {
    1133           0 :         zend_long who = PRIO_PROCESS;
    1134           0 :         zend_long pid = getpid();
    1135             :         zend_long pri;
    1136             : 
    1137           0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|ll", &pri, &pid, &who) == FAILURE) {
    1138           0 :                 RETURN_FALSE;
    1139             :         }
    1140             : 
    1141           0 :         if (setpriority(who, pid, pri)) {
    1142           0 :                 PCNTL_G(last_error) = errno;
    1143           0 :                 switch (errno) {
    1144             :                         case ESRCH:
    1145           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: No process was located using the given parameters", errno);
    1146           0 :                                 break;
    1147             :                         case EINVAL:
    1148           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: Invalid identifier flag", errno);
    1149           0 :                                 break;
    1150             :                         case EPERM:
    1151           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);
    1152           0 :                                 break;
    1153             :                         case EACCES:
    1154           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: Only a super user may attempt to increase the process priority", errno);
    1155           0 :                                 break;
    1156             :                         default:
    1157           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error %d has occurred", errno);
    1158             :                                 break;
    1159             :                 }
    1160           0 :                 RETURN_FALSE;
    1161             :         }
    1162             :         
    1163           0 :         RETURN_TRUE;
    1164             : }
    1165             : /* }}} */
    1166             : #endif
    1167             : 
    1168             : /* {{{ proto int pcntl_get_last_error(void)
    1169             :    Retrieve the error number set by the last pcntl function which failed. */
    1170           2 : PHP_FUNCTION(pcntl_get_last_error)
    1171             : {
    1172           2 :         RETURN_LONG(PCNTL_G(last_error));
    1173             : }
    1174             : /* }}} */
    1175             : 
    1176             : /* {{{ proto string pcntl_strerror(int errno)
    1177             :    Retrieve the system error message associated with the given errno. */
    1178           0 : PHP_FUNCTION(pcntl_strerror)
    1179             : {
    1180             :         zend_long error;
    1181             : 
    1182           0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &error) == FAILURE) {
    1183           0 :                 RETURN_FALSE;
    1184             :         }
    1185             : 
    1186           0 :         RETURN_STRING(strerror(error));
    1187             : }
    1188             : /* }}} */
    1189             : 
    1190             : /* Our custom signal handler that calls the appropriate php_function */
    1191           4 : static void pcntl_signal_handler(int signo)
    1192             : {
    1193             :         struct php_pcntl_pending_signal *psig;
    1194             :         TSRMLS_FETCH();
    1195             :         
    1196           4 :         psig = PCNTL_G(spares);
    1197           4 :         if (!psig) {
    1198             :                 /* oops, too many signals for us to track, so we'll forget about this one */
    1199           0 :                 return;
    1200             :         }
    1201           4 :         PCNTL_G(spares) = psig->next;
    1202             : 
    1203           4 :         psig->signo = signo;
    1204           4 :         psig->next = NULL;
    1205             : 
    1206             :         /* the head check is important, as the tick handler cannot atomically clear both
    1207             :          * the head and tail */
    1208           4 :         if (PCNTL_G(head) && PCNTL_G(tail)) {
    1209           0 :                 PCNTL_G(tail)->next = psig;
    1210             :         } else {
    1211           4 :                 PCNTL_G(head) = psig;
    1212             :         }
    1213           4 :         PCNTL_G(tail) = psig;
    1214             : }
    1215             : 
    1216          36 : void pcntl_signal_dispatch()
    1217             : {
    1218             :         zval param, *handle, retval;
    1219             :         struct php_pcntl_pending_signal *queue, *next;
    1220             :         sigset_t mask;
    1221             :         sigset_t old_mask;
    1222             :         TSRMLS_FETCH();
    1223             :                 
    1224             :         /* Mask all signals */
    1225          36 :         sigfillset(&mask);
    1226          36 :         sigprocmask(SIG_BLOCK, &mask, &old_mask);
    1227             : 
    1228             :         /* Bail if the queue is empty or if we are already playing the queue*/
    1229          36 :         if (! PCNTL_G(head) || PCNTL_G(processing_signal_queue)) {
    1230          33 :                 sigprocmask(SIG_SETMASK, &old_mask, NULL);
    1231          33 :                 return;
    1232             :         }
    1233             : 
    1234             :         /* Prevent reentrant handler calls */
    1235           3 :         PCNTL_G(processing_signal_queue) = 1;
    1236             : 
    1237           3 :         queue = PCNTL_G(head);
    1238           3 :         PCNTL_G(head) = NULL; /* simple stores are atomic */
    1239             :         
    1240             :         /* Allocate */
    1241             : 
    1242           9 :         while (queue) {
    1243           3 :                 if ((handle = zend_hash_index_find(&PCNTL_G(php_signal_table), queue->signo)) != NULL) {
    1244           3 :                         ZVAL_NULL(&retval);
    1245           3 :                         ZVAL_LONG(&param, queue->signo);
    1246             : 
    1247             :                         /* Call php signal handler - Note that we do not report errors, and we ignore the return value */
    1248             :                         /* FIXME: this is probably broken when multiple signals are handled in this while loop (retval) */
    1249           3 :                         call_user_function(EG(function_table), NULL, handle, &retval, 1, &param TSRMLS_CC);
    1250           3 :                         zval_ptr_dtor(&param);
    1251           3 :                         zval_ptr_dtor(&retval);
    1252             :                 }
    1253             : 
    1254           3 :                 next = queue->next;
    1255           3 :                 queue->next = PCNTL_G(spares);
    1256           3 :                 PCNTL_G(spares) = queue;
    1257           3 :                 queue = next;
    1258             :         }
    1259             : 
    1260             :         /* Re-enable queue */
    1261           3 :         PCNTL_G(processing_signal_queue) = 0;
    1262             :         
    1263             :         /* return signal mask to previous state */
    1264           3 :         sigprocmask(SIG_SETMASK, &old_mask, NULL);
    1265             : }
    1266             : 
    1267             : 
    1268             : 
    1269             : /*
    1270             :  * Local variables:
    1271             :  * tab-width: 4
    1272             :  * c-basic-offset: 4
    1273             :  * indent-tabs-mode: t
    1274             :  * End:
    1275             :  */

Generated by: LCOV version 1.10

Generated at Sat, 22 Nov 2014 23:01:20 +0000 (5 hours ago)

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