2001-06-12 16:54:25 +08:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2019-01-30 17:03:12 +08:00
| Copyright ( c ) The PHP Group |
2001-06-12 16:54:25 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2006-01-01 20:51:34 +08:00
| This source file is subject to version 3.01 of the PHP license , |
2001-06-12 16:54:25 +08:00
| that is bundled with this package in the file LICENSE , and is |
2003-06-11 04:04:29 +08:00
| available through the world - wide - web at the following url : |
2021-05-06 18:16:35 +08:00
| https : //www.php.net/license/3_01.txt |
2001-06-12 16:54:25 +08:00
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world - wide - web , please send a note to |
| license @ php . net so we can mail you a copy immediately . |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2002-02-28 16:29:35 +08:00
| Author : Jason Greene < jason @ inetgurus . net > |
2001-06-12 16:54:25 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
2001-06-20 05:42:57 +08:00
# define PCNTL_DEBUG 0
# if PCNTL_DEBUG
# define DEBUG_OUT printf("DEBUG: ");printf
2002-08-22 12:20:10 +08:00
# define IF_DEBUG(z) z
2001-06-20 05:42:57 +08:00
# else
2002-08-22 12:20:10 +08:00
# define IF_DEBUG(z)
2001-06-20 05:42:57 +08:00
# endif
2001-06-12 16:54:25 +08:00
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include "php.h"
# include "php_ini.h"
2002-03-17 16:10:04 +08:00
# include "ext/standard/info.h"
2001-06-12 16:54:25 +08:00
# include "php_pcntl.h"
2019-08-27 01:06:18 +08:00
# include "pcntl_arginfo.h"
2008-08-05 23:12:19 +08:00
# include "php_signal.h"
# include "php_ticks.h"
2001-06-12 16:54:25 +08:00
2020-05-20 19:59:44 +08:00
# if defined(HAVE_GETPRIORITY) || defined(HAVE_SETPRIORITY) || defined(HAVE_WAIT3)
2008-08-05 23:12:19 +08:00
# include <sys/wait.h>
2003-02-18 09:41:06 +08:00
# include <sys/time.h>
# include <sys/resource.h>
# endif
2010-11-02 04:10:17 +08:00
# include <errno.h>
2019-01-22 07:56:43 +08:00
# ifdef HAVE_UNSHARE
# include <sched.h>
# endif
2010-11-02 04:10:17 +08:00
2015-08-05 22:42:42 +08:00
# ifndef NSIG
# ifdef SIGRTMAX
# define NSIG (SIGRTMAX + 1)
# else
# define NSIG 32
# endif
# endif
2001-06-12 16:54:25 +08:00
ZEND_DECLARE_MODULE_GLOBALS ( pcntl )
2006-06-16 02:33:09 +08:00
static PHP_GINIT_FUNCTION ( pcntl ) ;
2001-06-12 16:54:25 +08:00
zend_module_entry pcntl_module_entry = {
2001-10-12 07:33:59 +08:00
STANDARD_MODULE_HEADER ,
" pcntl " ,
2020-04-20 02:05:16 +08:00
ext_functions ,
2001-06-12 16:54:25 +08:00
PHP_MINIT ( pcntl ) ,
PHP_MSHUTDOWN ( pcntl ) ,
2002-08-22 12:20:10 +08:00
PHP_RINIT ( pcntl ) ,
PHP_RSHUTDOWN ( pcntl ) ,
2001-06-12 16:54:25 +08:00
PHP_MINFO ( pcntl ) ,
2015-03-24 03:54:55 +08:00
PHP_PCNTL_VERSION ,
2006-06-16 02:33:09 +08:00
PHP_MODULE_GLOBALS ( pcntl ) ,
PHP_GINIT ( pcntl ) ,
NULL ,
NULL ,
STANDARD_MODULE_PROPERTIES_EX
2001-06-12 16:54:25 +08:00
} ;
# ifdef COMPILE_DL_PCNTL
2019-03-12 19:15:47 +08:00
# ifdef ZTS
ZEND_TSRMLS_CACHE_DEFINE ( )
# endif
2001-06-12 16:54:25 +08:00
ZEND_GET_MODULE ( pcntl )
# endif
2003-05-30 07:39:41 +08:00
2016-07-06 18:11:47 +08:00
static void ( * orig_interrupt_function ) ( zend_execute_data * execute_data ) ;
2016-06-14 06:33:19 +08:00
# ifdef HAVE_STRUCT_SIGINFO_T
static void pcntl_signal_handler ( int , siginfo_t * , void * ) ;
static void pcntl_siginfo_to_zval ( int , siginfo_t * , zval * ) ;
# else
2003-05-30 07:39:41 +08:00
static void pcntl_signal_handler ( int ) ;
2016-06-14 06:33:19 +08:00
# endif
2008-07-30 00:46:11 +08:00
static void pcntl_signal_dispatch ( ) ;
2016-07-06 18:11:47 +08:00
static void pcntl_interrupt_function ( zend_execute_data * execute_data ) ;
2015-01-03 17:22:58 +08:00
2001-06-12 16:54:25 +08:00
void php_register_signal_constants ( INIT_FUNC_ARGS )
{
2002-03-17 06:31:57 +08:00
2001-07-06 13:48:52 +08:00
/* Wait Constants */
# ifdef WNOHANG
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " WNOHANG " , ( zend_long ) WNOHANG , CONST_CS | CONST_PERSISTENT ) ;
2001-07-06 13:48:52 +08:00
# endif
# ifdef WUNTRACED
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " WUNTRACED " , ( zend_long ) WUNTRACED , CONST_CS | CONST_PERSISTENT ) ;
2001-07-06 13:48:52 +08:00
# endif
2015-02-23 21:38:55 +08:00
# ifdef HAVE_WCONTINUED
REGISTER_LONG_CONSTANT ( " WCONTINUED " , ( zend_long ) WCONTINUED , CONST_CS | CONST_PERSISTENT ) ;
# endif
2001-07-06 13:48:52 +08:00
/* Signal Constants */
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " SIG_IGN " , ( zend_long ) SIG_IGN , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIG_DFL " , ( zend_long ) SIG_DFL , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIG_ERR " , ( zend_long ) SIG_ERR , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGHUP " , ( zend_long ) SIGHUP , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGINT " , ( zend_long ) SIGINT , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGQUIT " , ( zend_long ) SIGQUIT , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGILL " , ( zend_long ) SIGILL , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGTRAP " , ( zend_long ) SIGTRAP , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGABRT " , ( zend_long ) SIGABRT , CONST_CS | CONST_PERSISTENT ) ;
2002-12-12 20:23:32 +08:00
# ifdef SIGIOT
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " SIGIOT " , ( zend_long ) SIGIOT , CONST_CS | CONST_PERSISTENT ) ;
# endif
REGISTER_LONG_CONSTANT ( " SIGBUS " , ( zend_long ) SIGBUS , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGFPE " , ( zend_long ) SIGFPE , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGKILL " , ( zend_long ) SIGKILL , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGUSR1 " , ( zend_long ) SIGUSR1 , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGSEGV " , ( zend_long ) SIGSEGV , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGUSR2 " , ( zend_long ) SIGUSR2 , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGPIPE " , ( zend_long ) SIGPIPE , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGALRM " , ( zend_long ) SIGALRM , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGTERM " , ( zend_long ) SIGTERM , CONST_CS | CONST_PERSISTENT ) ;
2001-06-13 09:13:05 +08:00
# ifdef SIGSTKFLT
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " SIGSTKFLT " , ( zend_long ) SIGSTKFLT , CONST_CS | CONST_PERSISTENT ) ;
2015-01-03 17:22:58 +08:00
# endif
2001-06-13 09:13:05 +08:00
# ifdef SIGCLD
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " SIGCLD " , ( zend_long ) SIGCLD , CONST_CS | CONST_PERSISTENT ) ;
2001-06-13 09:13:05 +08:00
# endif
# ifdef SIGCHLD
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " SIGCHLD " , ( zend_long ) SIGCHLD , CONST_CS | CONST_PERSISTENT ) ;
# endif
REGISTER_LONG_CONSTANT ( " SIGCONT " , ( zend_long ) SIGCONT , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGSTOP " , ( zend_long ) SIGSTOP , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGTSTP " , ( zend_long ) SIGTSTP , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGTTIN " , ( zend_long ) SIGTTIN , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGTTOU " , ( zend_long ) SIGTTOU , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGURG " , ( zend_long ) SIGURG , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGXCPU " , ( zend_long ) SIGXCPU , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGXFSZ " , ( zend_long ) SIGXFSZ , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGVTALRM " , ( zend_long ) SIGVTALRM , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGPROF " , ( zend_long ) SIGPROF , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGWINCH " , ( zend_long ) SIGWINCH , CONST_CS | CONST_PERSISTENT ) ;
2001-06-26 12:54:47 +08:00
# ifdef SIGPOLL
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " SIGPOLL " , ( zend_long ) SIGPOLL , CONST_CS | CONST_PERSISTENT ) ;
2001-06-26 12:54:47 +08:00
# endif
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " SIGIO " , ( zend_long ) SIGIO , CONST_CS | CONST_PERSISTENT ) ;
2001-06-26 12:54:47 +08:00
# ifdef SIGPWR
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " SIGPWR " , ( zend_long ) SIGPWR , CONST_CS | CONST_PERSISTENT ) ;
2001-06-26 12:54:47 +08:00
# endif
2004-12-14 22:01:06 +08:00
# ifdef SIGSYS
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " SIGSYS " , ( zend_long ) SIGSYS , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGBABY " , ( zend_long ) SIGSYS , CONST_CS | CONST_PERSISTENT ) ;
2004-12-14 22:01:06 +08:00
# endif
2015-08-05 22:42:42 +08:00
# ifdef SIGRTMIN
REGISTER_LONG_CONSTANT ( " SIGRTMIN " , ( zend_long ) SIGRTMIN , CONST_CS | CONST_PERSISTENT ) ;
# endif
# ifdef SIGRTMAX
REGISTER_LONG_CONSTANT ( " SIGRTMAX " , ( zend_long ) SIGRTMAX , CONST_CS | CONST_PERSISTENT ) ;
# endif
2003-02-18 09:41:06 +08:00
2020-05-20 19:59:44 +08:00
# if defined(HAVE_GETPRIORITY) || defined(HAVE_SETPRIORITY)
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " PRIO_PGRP " , PRIO_PGRP , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " PRIO_USER " , PRIO_USER , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " PRIO_PROCESS " , PRIO_PROCESS , CONST_CS | CONST_PERSISTENT ) ;
2003-02-18 09:41:06 +08:00
# endif
2008-07-30 00:59:10 +08:00
/* {{{ "how" argument for sigprocmask */
# ifdef HAVE_SIGPROCMASK
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " SIG_BLOCK " , SIG_BLOCK , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIG_UNBLOCK " , SIG_UNBLOCK , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIG_SETMASK " , SIG_SETMASK , CONST_CS | CONST_PERSISTENT ) ;
2008-07-30 00:59:10 +08:00
# endif
/* }}} */
/* {{{ si_code */
2020-05-20 19:59:44 +08:00
# if defined(HAVE_SIGWAITINFO) && defined(HAVE_SIGTIMEDWAIT)
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " SI_USER " , SI_USER , CONST_CS | CONST_PERSISTENT ) ;
2008-07-30 00:59:10 +08:00
# ifdef SI_NOINFO
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " SI_NOINFO " , SI_NOINFO , CONST_CS | CONST_PERSISTENT ) ;
2008-07-30 00:59:10 +08:00
# endif
# ifdef SI_KERNEL
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " SI_KERNEL " , SI_KERNEL , CONST_CS | CONST_PERSISTENT ) ;
2008-07-30 00:59:10 +08:00
# endif
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " SI_QUEUE " , SI_QUEUE , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SI_TIMER " , SI_TIMER , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SI_MESGQ " , SI_MESGQ , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SI_ASYNCIO " , SI_ASYNCIO , CONST_CS | CONST_PERSISTENT ) ;
2008-07-30 00:59:10 +08:00
# ifdef SI_SIGIO
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " SI_SIGIO " , SI_SIGIO , CONST_CS | CONST_PERSISTENT ) ;
2008-07-30 00:59:10 +08:00
# endif
# ifdef SI_TKILL
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " SI_TKILL " , SI_TKILL , CONST_CS | CONST_PERSISTENT ) ;
2008-07-30 00:59:10 +08:00
# endif
/* si_code for SIGCHILD */
2009-03-26 07:34:08 +08:00
# ifdef CLD_EXITED
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " CLD_EXITED " , CLD_EXITED , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef CLD_KILLED
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " CLD_KILLED " , CLD_KILLED , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef CLD_DUMPED
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " CLD_DUMPED " , CLD_DUMPED , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef CLD_TRAPPED
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " CLD_TRAPPED " , CLD_TRAPPED , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef CLD_STOPPED
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " CLD_STOPPED " , CLD_STOPPED , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef CLD_CONTINUED
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " CLD_CONTINUED " , CLD_CONTINUED , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
2008-07-30 00:59:10 +08:00
/* si_code for SIGTRAP */
2009-03-26 07:34:08 +08:00
# ifdef TRAP_BRKPT
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " TRAP_BRKPT " , TRAP_BRKPT , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef TRAP_TRACE
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " TRAP_TRACE " , TRAP_TRACE , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
2008-07-30 00:59:10 +08:00
/* si_code for SIGPOLL */
2009-03-26 07:34:08 +08:00
# ifdef POLL_IN
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " POLL_IN " , POLL_IN , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef POLL_OUT
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " POLL_OUT " , POLL_OUT , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef POLL_MSG
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " POLL_MSG " , POLL_MSG , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef POLL_ERR
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " POLL_ERR " , POLL_ERR , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef POLL_PRI
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " POLL_PRI " , POLL_PRI , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef POLL_HUP
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " POLL_HUP " , POLL_HUP , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
2008-07-30 00:59:10 +08:00
2009-03-26 07:34:08 +08:00
# ifdef ILL_ILLOPC
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " ILL_ILLOPC " , ILL_ILLOPC , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef ILL_ILLOPN
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " ILL_ILLOPN " , ILL_ILLOPN , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef ILL_ILLADR
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " ILL_ILLADR " , ILL_ILLADR , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef ILL_ILLTRP
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " ILL_ILLTRP " , ILL_ILLTRP , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef ILL_PRVOPC
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " ILL_PRVOPC " , ILL_PRVOPC , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef ILL_PRVREG
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " ILL_PRVREG " , ILL_PRVREG , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef ILL_COPROC
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " ILL_COPROC " , ILL_COPROC , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef ILL_BADSTK
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " ILL_BADSTK " , ILL_BADSTK , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
2008-07-30 00:59:10 +08:00
2009-03-26 07:34:08 +08:00
# ifdef FPE_INTDIV
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " FPE_INTDIV " , FPE_INTDIV , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef FPE_INTOVF
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " FPE_INTOVF " , FPE_INTOVF , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef FPE_FLTDIV
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " FPE_FLTDIV " , FPE_FLTDIV , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef FPE_FLTOVF
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " FPE_FLTOVF " , FPE_FLTOVF , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef FPE_FLTUND
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " FPE_FLTUND " , FPE_FLTINV , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef FPE_FLTRES
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " FPE_FLTRES " , FPE_FLTRES , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef FPE_FLTINV
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " FPE_FLTINV " , FPE_FLTINV , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef FPE_FLTSUB
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " FPE_FLTSUB " , FPE_FLTSUB , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
2008-07-30 00:59:10 +08:00
2009-03-26 07:34:08 +08:00
# ifdef SEGV_MAPERR
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " SEGV_MAPERR " , SEGV_MAPERR , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef SEGV_ACCERR
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " SEGV_ACCERR " , SEGV_ACCERR , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
2008-07-30 00:59:10 +08:00
2009-03-26 07:34:08 +08:00
# ifdef BUS_ADRALN
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " BUS_ADRALN " , BUS_ADRALN , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef BUS_ADRERR
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " BUS_ADRERR " , BUS_ADRERR , CONST_CS | CONST_PERSISTENT ) ;
2009-03-26 07:34:08 +08:00
# endif
# ifdef BUS_OBJERR
2014-08-26 01:24:55 +08:00
REGISTER_LONG_CONSTANT ( " BUS_OBJERR " , BUS_OBJERR , CONST_CS | CONST_PERSISTENT ) ;
2008-07-30 00:59:10 +08:00
# endif
2020-05-20 19:59:44 +08:00
# endif /* defined(HAVE_SIGWAITINFO) && defined(HAVE_SIGTIMEDWAIT) */
2008-07-30 00:59:10 +08:00
/* }}} */
2019-01-22 07:56:43 +08:00
/* unshare(/clone) constants */
# ifdef HAVE_UNSHARE
REGISTER_LONG_CONSTANT ( " CLONE_NEWNS " , CLONE_NEWNS , CONST_CS | CONST_PERSISTENT ) ;
# ifdef CLONE_NEWIPC
REGISTER_LONG_CONSTANT ( " CLONE_NEWIPC " , CLONE_NEWIPC , CONST_CS | CONST_PERSISTENT ) ;
# endif
# ifdef CLONE_NEWUTS
REGISTER_LONG_CONSTANT ( " CLONE_NEWUTS " , CLONE_NEWUTS , CONST_CS | CONST_PERSISTENT ) ;
# endif
# ifdef CLONE_NEWNET
REGISTER_LONG_CONSTANT ( " CLONE_NEWNET " , CLONE_NEWNET , CONST_CS | CONST_PERSISTENT ) ;
# endif
# ifdef CLONE_NEWPID
REGISTER_LONG_CONSTANT ( " CLONE_NEWPID " , CLONE_NEWPID , CONST_CS | CONST_PERSISTENT ) ;
# endif
# ifdef CLONE_NEWUSER
REGISTER_LONG_CONSTANT ( " CLONE_NEWUSER " , CLONE_NEWUSER , CONST_CS | CONST_PERSISTENT ) ;
# endif
# ifdef CLONE_NEWCGROUP
REGISTER_LONG_CONSTANT ( " CLONE_NEWCGROUP " , CLONE_NEWCGROUP , CONST_CS | CONST_PERSISTENT ) ;
# endif
# endif
2001-06-12 16:54:25 +08:00
}
2001-06-20 05:42:57 +08:00
2010-11-02 04:10:17 +08:00
static void php_pcntl_register_errno_constants ( INIT_FUNC_ARGS )
{
# ifdef EINTR
REGISTER_PCNTL_ERRNO_CONSTANT ( EINTR ) ;
# endif
# ifdef ECHILD
REGISTER_PCNTL_ERRNO_CONSTANT ( ECHILD ) ;
# endif
# ifdef EINVAL
REGISTER_PCNTL_ERRNO_CONSTANT ( EINVAL ) ;
# endif
# ifdef EAGAIN
REGISTER_PCNTL_ERRNO_CONSTANT ( EAGAIN ) ;
# endif
# ifdef ESRCH
REGISTER_PCNTL_ERRNO_CONSTANT ( ESRCH ) ;
# endif
# ifdef EACCES
REGISTER_PCNTL_ERRNO_CONSTANT ( EACCES ) ;
# endif
# ifdef EPERM
REGISTER_PCNTL_ERRNO_CONSTANT ( EPERM ) ;
# endif
# ifdef ENOMEM
REGISTER_PCNTL_ERRNO_CONSTANT ( ENOMEM ) ;
# endif
# ifdef E2BIG
REGISTER_PCNTL_ERRNO_CONSTANT ( E2BIG ) ;
# endif
# ifdef EFAULT
REGISTER_PCNTL_ERRNO_CONSTANT ( EFAULT ) ;
# endif
# ifdef EIO
REGISTER_PCNTL_ERRNO_CONSTANT ( EIO ) ;
# endif
# ifdef EISDIR
REGISTER_PCNTL_ERRNO_CONSTANT ( EISDIR ) ;
# endif
# ifdef ELIBBAD
REGISTER_PCNTL_ERRNO_CONSTANT ( ELIBBAD ) ;
# endif
# ifdef ELOOP
REGISTER_PCNTL_ERRNO_CONSTANT ( ELOOP ) ;
# endif
# ifdef EMFILE
REGISTER_PCNTL_ERRNO_CONSTANT ( EMFILE ) ;
# endif
# ifdef ENAMETOOLONG
REGISTER_PCNTL_ERRNO_CONSTANT ( ENAMETOOLONG ) ;
# endif
# ifdef ENFILE
REGISTER_PCNTL_ERRNO_CONSTANT ( ENFILE ) ;
# endif
# ifdef ENOENT
REGISTER_PCNTL_ERRNO_CONSTANT ( ENOENT ) ;
# endif
# ifdef ENOEXEC
REGISTER_PCNTL_ERRNO_CONSTANT ( ENOEXEC ) ;
# endif
# ifdef ENOTDIR
REGISTER_PCNTL_ERRNO_CONSTANT ( ENOTDIR ) ;
# endif
# ifdef ETXTBSY
REGISTER_PCNTL_ERRNO_CONSTANT ( ETXTBSY ) ;
# endif
2019-01-22 07:56:43 +08:00
# ifdef ENOSPC
REGISTER_PCNTL_ERRNO_CONSTANT ( ENOSPC ) ;
# endif
# ifdef EUSERS
REGISTER_PCNTL_ERRNO_CONSTANT ( EUSERS ) ;
# endif
2010-11-02 04:10:17 +08:00
}
2006-06-16 02:33:09 +08:00
static PHP_GINIT_FUNCTION ( pcntl )
2015-01-03 17:22:58 +08:00
{
2019-03-12 19:15:47 +08:00
# if defined(COMPILE_DL_PCNTL) && defined(ZTS)
ZEND_TSRMLS_CACHE_UPDATE ( ) ;
# endif
2005-05-07 22:58:12 +08:00
memset ( pcntl_globals , 0 , sizeof ( * pcntl_globals ) ) ;
2001-07-31 03:40:29 +08:00
}
2002-08-22 12:20:10 +08:00
PHP_RINIT_FUNCTION ( pcntl )
2001-07-31 03:40:29 +08:00
{
2019-02-21 03:36:51 +08:00
php_add_tick_function ( pcntl_signal_dispatch , NULL ) ;
2005-05-07 22:58:12 +08:00
zend_hash_init ( & PCNTL_G ( php_signal_table ) , 16 , NULL , ZVAL_PTR_DTOR , 0 ) ;
PCNTL_G ( head ) = PCNTL_G ( tail ) = PCNTL_G ( spares ) = NULL ;
2016-07-06 18:11:47 +08:00
PCNTL_G ( async_signals ) = 0 ;
2020-10-22 20:18:45 +08:00
PCNTL_G ( last_error ) = 0 ;
2002-08-22 12:20:10 +08:00
return SUCCESS ;
2001-07-31 03:40:29 +08:00
}
PHP_MINIT_FUNCTION ( pcntl )
{
2002-03-17 06:31:57 +08:00
php_register_signal_constants ( INIT_FUNC_ARGS_PASSTHRU ) ;
2010-11-02 04:10:17 +08:00
php_pcntl_register_errno_constants ( INIT_FUNC_ARGS_PASSTHRU ) ;
2016-07-06 18:11:47 +08:00
orig_interrupt_function = zend_interrupt_function ;
zend_interrupt_function = pcntl_interrupt_function ;
2002-08-22 12:20:10 +08:00
2001-06-12 16:54:25 +08:00
return SUCCESS ;
}
2001-07-31 03:40:29 +08:00
2001-06-12 16:54:25 +08:00
PHP_MSHUTDOWN_FUNCTION ( pcntl )
{
return SUCCESS ;
}
2002-08-22 12:20:10 +08:00
PHP_RSHUTDOWN_FUNCTION ( pcntl )
{
2005-05-07 22:58:12 +08:00
struct php_pcntl_pending_signal * sig ;
/* FIXME: if a signal is delivered after this point, things will go pear shaped;
* need to remove signal handlers */
2002-08-22 12:20:10 +08:00
zend_hash_destroy ( & PCNTL_G ( php_signal_table ) ) ;
2005-05-07 22:58:12 +08:00
while ( PCNTL_G ( head ) ) {
sig = PCNTL_G ( head ) ;
PCNTL_G ( head ) = sig - > next ;
efree ( sig ) ;
}
while ( PCNTL_G ( spares ) ) {
sig = PCNTL_G ( spares ) ;
PCNTL_G ( spares ) = sig - > next ;
efree ( sig ) ;
}
2002-08-22 12:20:10 +08:00
return SUCCESS ;
}
2001-07-31 03:40:29 +08:00
2001-06-12 16:54:25 +08:00
PHP_MINFO_FUNCTION ( pcntl )
{
php_info_print_table_start ( ) ;
php_info_print_table_header ( 2 , " pcntl support " , " enabled " ) ;
php_info_print_table_end ( ) ;
}
2001-07-06 13:48:52 +08:00
2020-07-01 21:32:55 +08:00
/* {{{ Forks the currently running process following the same behavior as the UNIX fork() system call*/
2001-06-12 16:54:25 +08:00
PHP_FUNCTION ( pcntl_fork )
{
pid_t id ;
2019-08-27 23:25:19 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
2019-12-31 18:27:02 +08:00
RETURN_THROWS ( ) ;
2019-08-27 23:25:19 +08:00
}
2002-03-17 06:31:57 +08:00
id = fork ( ) ;
2001-06-12 16:54:25 +08:00
if ( id = = - 1 ) {
2010-11-02 04:10:17 +08:00
PCNTL_G ( last_error ) = errno ;
2014-12-14 06:06:14 +08:00
php_error_docref ( NULL , E_WARNING , " Error %d " , errno ) ;
2001-06-12 16:54:25 +08:00
}
2015-01-03 17:22:58 +08:00
2014-08-26 17:23:25 +08:00
RETURN_LONG ( ( zend_long ) id ) ;
2001-06-12 16:54:25 +08:00
}
/* }}} */
2020-07-01 21:32:55 +08:00
/* {{{ Set an alarm clock for delivery of a signal*/
2002-06-04 23:51:25 +08:00
PHP_FUNCTION ( pcntl_alarm )
{
2014-08-26 01:24:55 +08:00
zend_long seconds ;
2002-06-04 23:51:25 +08:00
2019-08-27 23:25:19 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " l " , & seconds ) = = FAILURE ) {
2019-12-31 18:27:02 +08:00
RETURN_THROWS ( ) ;
2019-08-27 23:25:19 +08:00
}
2015-01-03 17:22:58 +08:00
2019-08-27 23:25:19 +08:00
RETURN_LONG ( ( zend_long ) alarm ( seconds ) ) ;
2002-06-04 23:51:25 +08:00
}
/* }}} */
2014-12-11 22:01:55 +08:00
# define PHP_RUSAGE_PARA(from, to, field) \
add_assoc_long ( to , # field , from . field )
2017-08-30 04:03:56 +08:00
# ifndef _OSD_POSIX
2014-12-11 22:01:55 +08:00
# define PHP_RUSAGE_SPECIAL(from, to) \
PHP_RUSAGE_PARA ( from , to , ru_oublock ) ; \
PHP_RUSAGE_PARA ( from , to , ru_inblock ) ; \
PHP_RUSAGE_PARA ( from , to , ru_msgsnd ) ; \
PHP_RUSAGE_PARA ( from , to , ru_msgrcv ) ; \
PHP_RUSAGE_PARA ( from , to , ru_maxrss ) ; \
PHP_RUSAGE_PARA ( from , to , ru_ixrss ) ; \
PHP_RUSAGE_PARA ( from , to , ru_idrss ) ; \
PHP_RUSAGE_PARA ( from , to , ru_minflt ) ; \
PHP_RUSAGE_PARA ( from , to , ru_majflt ) ; \
PHP_RUSAGE_PARA ( from , to , ru_nsignals ) ; \
PHP_RUSAGE_PARA ( from , to , ru_nvcsw ) ; \
PHP_RUSAGE_PARA ( from , to , ru_nivcsw ) ; \
PHP_RUSAGE_PARA ( from , to , ru_nswap ) ;
# else /*_OSD_POSIX*/
# define PHP_RUSAGE_SPECIAL(from, to)
# endif
# define PHP_RUSAGE_COMMON(from ,to) \
PHP_RUSAGE_PARA ( from , to , ru_utime . tv_usec ) ; \
PHP_RUSAGE_PARA ( from , to , ru_utime . tv_sec ) ; \
PHP_RUSAGE_PARA ( from , to , ru_stime . tv_usec ) ; \
PHP_RUSAGE_PARA ( from , to , ru_stime . tv_sec ) ;
# define PHP_RUSAGE_TO_ARRAY(from, to) \
if ( to ) { \
PHP_RUSAGE_SPECIAL ( from , to ) \
PHP_RUSAGE_COMMON ( from , to ) ; \
}
2020-07-01 21:32:55 +08:00
/* {{{ Waits on or returns the status of a forked child as defined by the waitpid() system call */
2001-06-12 16:54:25 +08:00
PHP_FUNCTION ( pcntl_waitpid )
{
2014-08-26 01:24:55 +08:00
zend_long pid , options = 0 ;
2014-12-11 22:01:55 +08:00
zval * z_status = NULL , * z_rusage = NULL ;
2002-04-24 05:21:41 +08:00
int status ;
pid_t child_id ;
2014-12-11 22:01:55 +08:00
# ifdef HAVE_WAIT4
struct rusage rusage ;
# endif
2001-06-12 16:54:25 +08:00
2019-01-07 19:28:51 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " lz|lz " , & pid , & z_status , & options , & z_rusage ) = = FAILURE ) {
2019-12-31 18:27:02 +08:00
RETURN_THROWS ( ) ;
2016-05-05 15:18:17 +08:00
}
2015-01-03 17:22:58 +08:00
2016-05-05 15:18:17 +08:00
status = zval_get_long ( z_status ) ;
2001-06-12 16:54:25 +08:00
2014-12-11 22:01:55 +08:00
# ifdef HAVE_WAIT4
if ( z_rusage ) {
2019-01-07 19:28:51 +08:00
z_rusage = zend_try_array_init ( z_rusage ) ;
if ( ! z_rusage ) {
2020-01-04 03:44:29 +08:00
RETURN_THROWS ( ) ;
2014-12-11 22:01:55 +08:00
}
memset ( & rusage , 0 , sizeof ( struct rusage ) ) ;
child_id = wait4 ( ( pid_t ) pid , & status , options , & rusage ) ;
} else {
child_id = waitpid ( ( pid_t ) pid , & status , options ) ;
}
# else
2002-04-24 05:21:41 +08:00
child_id = waitpid ( ( pid_t ) pid , & status , options ) ;
2014-12-11 22:01:55 +08:00
# endif
2002-04-24 05:21:41 +08:00
2010-11-02 04:10:17 +08:00
if ( child_id < 0 ) {
PCNTL_G ( last_error ) = errno ;
}
2014-12-11 22:01:55 +08:00
# ifdef HAVE_WAIT4
if ( child_id > 0 ) {
PHP_RUSAGE_TO_ARRAY ( rusage , z_rusage ) ;
}
# endif
2019-04-24 23:28:29 +08:00
ZEND_TRY_ASSIGN_REF_LONG ( z_status , status ) ;
2002-04-24 05:21:41 +08:00
2014-08-26 01:24:55 +08:00
RETURN_LONG ( ( zend_long ) child_id ) ;
2001-06-12 16:54:25 +08:00
}
/* }}} */
2020-07-01 21:32:55 +08:00
/* {{{ Waits on or returns the status of a forked child as defined by the waitpid() system call */
2003-10-29 01:08:18 +08:00
PHP_FUNCTION ( pcntl_wait )
{
2014-08-26 01:24:55 +08:00
zend_long options = 0 ;
2014-12-11 22:01:55 +08:00
zval * z_status = NULL , * z_rusage = NULL ;
2003-10-29 01:08:18 +08:00
int status ;
pid_t child_id ;
2014-12-11 22:01:55 +08:00
# ifdef HAVE_WAIT3
struct rusage rusage ;
# endif
2003-10-29 01:08:18 +08:00
2019-01-07 19:28:51 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " z|lz " , & z_status , & options , & z_rusage ) = = FAILURE ) {
2019-12-31 18:27:02 +08:00
RETURN_THROWS ( ) ;
2016-05-05 15:18:17 +08:00
}
2015-01-03 17:22:58 +08:00
2016-05-05 15:18:17 +08:00
status = zval_get_long ( z_status ) ;
2003-10-29 01:08:18 +08:00
# ifdef HAVE_WAIT3
2014-12-11 22:01:55 +08:00
if ( z_rusage ) {
2019-01-07 19:28:51 +08:00
z_rusage = zend_try_array_init ( z_rusage ) ;
if ( ! z_rusage ) {
2020-01-04 03:44:29 +08:00
RETURN_THROWS ( ) ;
2014-12-11 22:01:55 +08:00
}
memset ( & rusage , 0 , sizeof ( struct rusage ) ) ;
child_id = wait3 ( & status , options , & rusage ) ;
} else if ( options ) {
child_id = wait3 ( & status , options , NULL ) ;
} else {
2003-10-29 01:08:18 +08:00
child_id = wait ( & status ) ;
}
# else
child_id = wait ( & status ) ;
# endif
2010-11-02 04:10:17 +08:00
if ( child_id < 0 ) {
PCNTL_G ( last_error ) = errno ;
}
2014-12-11 22:01:55 +08:00
# ifdef HAVE_WAIT3
if ( child_id > 0 ) {
PHP_RUSAGE_TO_ARRAY ( rusage , z_rusage ) ;
}
# endif
2016-05-05 15:18:17 +08:00
2019-04-24 23:28:29 +08:00
ZEND_TRY_ASSIGN_REF_LONG ( z_status , status ) ;
2003-10-29 01:08:18 +08:00
2014-08-26 01:24:55 +08:00
RETURN_LONG ( ( zend_long ) child_id ) ;
2003-10-29 01:08:18 +08:00
}
/* }}} */
2014-12-11 22:01:55 +08:00
# undef PHP_RUSAGE_PARA
# undef PHP_RUSAGE_SPECIAL
# undef PHP_RUSAGE_COMMON
# undef PHP_RUSAGE_TO_ARRAY
2020-07-01 21:32:55 +08:00
/* {{{ Returns true if the child status code represents a successful exit */
2001-07-06 13:48:52 +08:00
PHP_FUNCTION ( pcntl_wifexited )
{
2014-08-26 01:24:55 +08:00
zend_long status_word ;
2008-06-22 23:16:11 +08:00
2014-12-14 06:06:14 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " l " , & status_word ) = = FAILURE ) {
2019-12-31 18:27:02 +08:00
RETURN_THROWS ( ) ;
2001-07-06 13:48:52 +08:00
}
2008-06-22 23:16:11 +08:00
2019-08-27 23:25:19 +08:00
# ifdef WIFEXITED
int int_status_word = ( int ) status_word ;
if ( WIFEXITED ( int_status_word ) ) {
2008-06-22 23:16:11 +08:00
RETURN_TRUE ;
2019-08-27 23:25:19 +08:00
}
2001-07-06 13:48:52 +08:00
# endif
2018-02-23 23:11:18 +08:00
2001-07-06 13:48:52 +08:00
RETURN_FALSE ;
}
/* }}} */
2020-07-01 21:32:55 +08:00
/* {{{ Returns true if the child status code represents a stopped process (WUNTRACED must have been used with waitpid) */
2001-07-06 13:48:52 +08:00
PHP_FUNCTION ( pcntl_wifstopped )
{
2014-08-26 01:24:55 +08:00
zend_long status_word ;
2008-06-22 23:16:11 +08:00
2014-12-14 06:06:14 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " l " , & status_word ) = = FAILURE ) {
2019-12-31 18:27:02 +08:00
RETURN_THROWS ( ) ;
2001-07-06 13:48:52 +08:00
}
2008-06-22 23:16:11 +08:00
2019-08-27 23:25:19 +08:00
# ifdef WIFSTOPPED
int int_status_word = ( int ) status_word ;
if ( WIFSTOPPED ( int_status_word ) ) {
2008-06-22 23:16:11 +08:00
RETURN_TRUE ;
2019-08-27 23:25:19 +08:00
}
2001-07-06 13:48:52 +08:00
# endif
2019-08-27 23:25:19 +08:00
2001-07-06 13:48:52 +08:00
RETURN_FALSE ;
}
/* }}} */
2020-07-01 21:32:55 +08:00
/* {{{ Returns true if the child status code represents a process that was terminated due to a signal */
2001-07-06 13:48:52 +08:00
PHP_FUNCTION ( pcntl_wifsignaled )
{
2014-08-26 01:24:55 +08:00
zend_long status_word ;
2008-06-22 23:16:11 +08:00
2014-12-14 06:06:14 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " l " , & status_word ) = = FAILURE ) {
2019-12-31 18:27:02 +08:00
RETURN_THROWS ( ) ;
2001-07-06 13:48:52 +08:00
}
2008-06-22 23:16:11 +08:00
2019-08-27 23:25:19 +08:00
# ifdef WIFSIGNALED
int int_status_word = ( int ) status_word ;
if ( WIFSIGNALED ( int_status_word ) ) {
2008-06-22 23:16:11 +08:00
RETURN_TRUE ;
2019-08-27 23:25:19 +08:00
}
2001-07-06 13:48:52 +08:00
# endif
2019-08-27 23:25:19 +08:00
2001-07-06 13:48:52 +08:00
RETURN_FALSE ;
}
/* }}} */
2020-07-01 21:32:55 +08:00
/* {{{ Returns true if the child status code represents a process that was resumed due to a SIGCONT signal */
2015-02-23 21:38:55 +08:00
PHP_FUNCTION ( pcntl_wifcontinued )
{
zend_long status_word ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " l " , & status_word ) = = FAILURE ) {
2019-12-31 18:27:02 +08:00
RETURN_THROWS ( ) ;
2015-02-23 21:38:55 +08:00
}
2019-08-27 23:25:19 +08:00
# ifdef HAVE_WCONTINUED
int int_status_word = ( int ) status_word ;
if ( WIFCONTINUED ( int_status_word ) ) {
2015-02-23 21:38:55 +08:00
RETURN_TRUE ;
2019-08-27 23:25:19 +08:00
}
2015-02-23 21:38:55 +08:00
# endif
RETURN_FALSE ;
}
/* }}} */
2001-07-06 13:48:52 +08:00
2020-07-01 21:32:55 +08:00
/* {{{ Returns the status code of a child's exit */
2001-07-06 13:48:52 +08:00
PHP_FUNCTION ( pcntl_wexitstatus )
{
2014-08-26 01:24:55 +08:00
zend_long status_word ;
2008-06-22 23:16:11 +08:00
2014-12-14 06:06:14 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " l " , & status_word ) = = FAILURE ) {
2019-12-31 18:27:02 +08:00
RETURN_THROWS ( ) ;
2001-07-06 13:48:52 +08:00
}
2019-08-27 23:25:19 +08:00
# ifdef WEXITSTATUS
int int_status_word = ( int ) status_word ;
2018-02-28 09:13:28 +08:00
RETURN_LONG ( WEXITSTATUS ( int_status_word ) ) ;
2001-07-06 13:48:52 +08:00
# else
RETURN_FALSE ;
# endif
}
/* }}} */
2020-07-01 21:32:55 +08:00
/* {{{ Returns the number of the signal that terminated the process who's status code is passed */
2001-07-06 13:48:52 +08:00
PHP_FUNCTION ( pcntl_wtermsig )
{
2014-08-26 01:24:55 +08:00
zend_long status_word ;
2008-06-22 23:16:11 +08:00
2014-12-14 06:06:14 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " l " , & status_word ) = = FAILURE ) {
2019-12-31 18:27:02 +08:00
RETURN_THROWS ( ) ;
2001-07-06 13:48:52 +08:00
}
2008-06-22 23:16:11 +08:00
2019-08-27 23:25:19 +08:00
# ifdef WTERMSIG
int int_status_word = ( int ) status_word ;
2018-02-28 09:13:28 +08:00
RETURN_LONG ( WTERMSIG ( int_status_word ) ) ;
2001-07-06 13:48:52 +08:00
# else
RETURN_FALSE ;
# endif
}
/* }}} */
2020-07-01 21:32:55 +08:00
/* {{{ Returns the number of the signal that caused the process to stop who's status code is passed */
2001-07-06 13:48:52 +08:00
PHP_FUNCTION ( pcntl_wstopsig )
{
2014-08-26 01:24:55 +08:00
zend_long status_word ;
2008-06-22 23:16:11 +08:00
2014-12-14 06:06:14 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " l " , & status_word ) = = FAILURE ) {
2019-12-31 18:27:02 +08:00
RETURN_THROWS ( ) ;
2001-07-06 13:48:52 +08:00
}
2019-08-27 23:25:19 +08:00
# ifdef WSTOPSIG
int int_status_word = ( int ) status_word ;
2018-02-28 09:13:28 +08:00
RETURN_LONG ( WSTOPSIG ( int_status_word ) ) ;
2001-07-06 13:48:52 +08:00
# else
RETURN_FALSE ;
# endif
}
/* }}} */
2020-07-01 21:32:55 +08:00
/* {{{ Executes specified program in current process space as defined by exec(2) */
2001-09-30 14:59:12 +08:00
PHP_FUNCTION ( pcntl_exec )
{
2008-09-13 03:49:18 +08:00
zval * args = NULL , * envs = NULL ;
2014-05-06 18:23:56 +08:00
zval * element ;
2001-09-30 14:59:12 +08:00
HashTable * args_hash , * envs_hash ;
2002-03-17 06:31:57 +08:00
int argc = 0 , argi = 0 ;
int envc = 0 , envi = 0 ;
char * * argv = NULL , * * envp = NULL ;
char * * current_arg , * * pair ;
2021-04-09 19:09:21 +08:00
size_t pair_length ;
2014-05-06 18:23:56 +08:00
zend_string * key ;
2001-09-30 14:59:12 +08:00
char * path ;
2014-08-27 21:31:48 +08:00
size_t path_len ;
2014-08-26 01:24:55 +08:00
zend_ulong key_num ;
2015-01-03 17:22:58 +08:00
2015-05-13 05:31:52 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " p|aa " , & path , & path_len , & args , & envs ) = = FAILURE ) {
2019-12-31 18:27:02 +08:00
RETURN_THROWS ( ) ;
2001-09-30 14:59:12 +08:00
}
2015-01-03 17:22:58 +08:00
2002-03-17 06:31:57 +08:00
if ( ZEND_NUM_ARGS ( ) > 1 ) {
2012-03-28 22:18:23 +08:00
/* Build argument list */
2019-02-26 22:32:18 +08:00
SEPARATE_ARRAY ( args ) ;
2015-09-25 03:39:59 +08:00
args_hash = Z_ARRVAL_P ( args ) ;
2002-03-17 06:31:57 +08:00
argc = zend_hash_num_elements ( args_hash ) ;
2015-01-03 17:22:58 +08:00
2004-06-30 09:12:06 +08:00
argv = safe_emalloc ( ( argc + 2 ) , sizeof ( char * ) , 0 ) ;
2002-03-17 06:31:57 +08:00
* argv = path ;
2014-05-28 21:30:05 +08:00
current_arg = argv + 1 ;
ZEND_HASH_FOREACH_VAL ( args_hash , element ) {
if ( argi > = argc ) break ;
2019-02-26 22:32:18 +08:00
if ( ! try_convert_to_string ( element ) ) {
efree ( argv ) ;
2020-01-04 00:04:06 +08:00
RETURN_THROWS ( ) ;
2019-02-26 22:32:18 +08:00
}
2014-05-06 18:23:56 +08:00
* current_arg = Z_STRVAL_P ( element ) ;
2014-05-28 21:30:05 +08:00
argi + + ;
current_arg + + ;
} ZEND_HASH_FOREACH_END ( ) ;
2019-02-26 22:32:18 +08:00
* current_arg = NULL ;
2001-09-30 14:59:12 +08:00
} else {
2004-06-30 09:12:06 +08:00
argv = emalloc ( 2 * sizeof ( char * ) ) ;
2019-02-26 22:32:18 +08:00
argv [ 0 ] = path ;
argv [ 1 ] = NULL ;
2001-09-30 14:59:12 +08:00
}
2002-03-17 06:31:57 +08:00
if ( ZEND_NUM_ARGS ( ) = = 3 ) {
2001-09-30 14:59:12 +08:00
/* Build environment pair list */
2019-02-26 22:32:18 +08:00
SEPARATE_ARRAY ( envs ) ;
2015-09-25 03:39:59 +08:00
envs_hash = Z_ARRVAL_P ( envs ) ;
2002-03-17 06:31:57 +08:00
envc = zend_hash_num_elements ( envs_hash ) ;
2015-01-03 17:22:58 +08:00
pair = envp = safe_emalloc ( ( envc + 1 ) , sizeof ( char * ) , 0 ) ;
2014-05-28 21:30:05 +08:00
ZEND_HASH_FOREACH_KEY_VAL ( envs_hash , key_num , key , element ) {
if ( envi > = envc ) break ;
if ( ! key ) {
2014-08-26 04:47:04 +08:00
key = zend_long_to_str ( key_num ) ;
2014-05-28 21:30:05 +08:00
} else {
2014-08-26 01:24:55 +08:00
zend_string_addref ( key ) ;
2001-09-30 14:59:12 +08:00
}
2002-05-07 03:48:39 +08:00
2019-02-26 22:32:18 +08:00
if ( ! try_convert_to_string ( element ) ) {
zend_string_release ( key ) ;
efree ( argv ) ;
efree ( envp ) ;
2020-01-04 00:04:06 +08:00
RETURN_THROWS ( ) ;
2019-02-26 22:32:18 +08:00
}
2002-05-07 03:48:39 +08:00
2015-01-03 17:22:58 +08:00
/* Length of element + equal sign + length of key + null */
2021-04-09 19:09:21 +08:00
ZEND_ASSERT ( Z_STRLEN_P ( element ) < SIZE_MAX & & ZSTR_LEN ( key ) < SIZE_MAX ) ;
* pair = safe_emalloc ( Z_STRLEN_P ( element ) + 1 , sizeof ( char ) , ZSTR_LEN ( key ) + 1 ) ;
2015-06-30 09:05:24 +08:00
pair_length = Z_STRLEN_P ( element ) + ZSTR_LEN ( key ) + 2 ;
strlcpy ( * pair , ZSTR_VAL ( key ) , ZSTR_LEN ( key ) + 1 ) ;
2001-09-30 14:59:12 +08:00
strlcat ( * pair , " = " , pair_length ) ;
2014-05-06 18:23:56 +08:00
strlcat ( * pair , Z_STRVAL_P ( element ) , pair_length ) ;
2015-01-03 17:22:58 +08:00
2001-09-30 14:59:12 +08:00
/* Cleanup */
2018-05-28 21:27:12 +08:00
zend_string_release_ex ( key , 0 ) ;
2014-05-28 21:30:05 +08:00
envi + + ;
pair + + ;
} ZEND_HASH_FOREACH_END ( ) ;
2002-03-17 06:31:57 +08:00
* ( pair ) = NULL ;
2009-09-30 21:04:28 +08:00
if ( execve ( path , argv , envp ) = = - 1 ) {
2010-11-02 04:10:17 +08:00
PCNTL_G ( last_error ) = errno ;
2014-12-14 06:06:14 +08:00
php_error_docref ( NULL , E_WARNING , " Error has occurred: (errno %d) %s " , errno , strerror ( errno ) ) ;
2009-09-30 21:04:28 +08:00
}
2015-01-03 17:22:58 +08:00
2009-09-30 21:04:28 +08:00
/* Cleanup */
2002-05-07 03:48:39 +08:00
for ( pair = envp ; * pair ! = NULL ; pair + + ) efree ( * pair ) ;
2004-06-30 09:12:06 +08:00
efree ( envp ) ;
2009-09-30 21:04:28 +08:00
} else {
if ( execv ( path , argv ) = = - 1 ) {
2010-11-02 04:10:17 +08:00
PCNTL_G ( last_error ) = errno ;
2014-12-14 06:06:14 +08:00
php_error_docref ( NULL , E_WARNING , " Error has occurred: (errno %d) %s " , errno , strerror ( errno ) ) ;
2009-09-30 21:04:28 +08:00
}
2002-05-07 03:48:39 +08:00
}
2004-06-30 09:12:06 +08:00
efree ( argv ) ;
2015-01-03 17:22:58 +08:00
2001-09-30 14:59:12 +08:00
RETURN_FALSE ;
}
/* }}} */
2020-07-01 21:32:55 +08:00
/* {{{ Assigns a system signal handler to a PHP function */
2001-06-12 16:54:25 +08:00
PHP_FUNCTION ( pcntl_signal )
{
2014-05-06 18:23:56 +08:00
zval * handle ;
2014-08-26 01:24:55 +08:00
zend_long signo ;
2021-01-15 19:30:54 +08:00
bool restart_syscalls = 1 ;
bool restart_syscalls_is_null = 1 ;
2019-12-18 03:03:42 +08:00
char * error = NULL ;
2001-06-12 16:54:25 +08:00
2019-01-14 20:04:37 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " lz|b! " , & signo , & handle , & restart_syscalls , & restart_syscalls_is_null ) = = FAILURE ) {
2019-12-31 18:27:02 +08:00
RETURN_THROWS ( ) ;
2001-06-12 16:54:25 +08:00
}
2020-08-18 04:37:20 +08:00
if ( signo < 1 ) {
zend_argument_value_error ( 1 , " must be greater than or equal to 1 " ) ;
RETURN_THROWS ( ) ;
}
if ( signo > = NSIG ) {
zend_argument_value_error ( 1 , " must be less than %d " , NSIG ) ;
RETURN_THROWS ( ) ;
2011-06-04 01:18:46 +08:00
}
2005-05-07 22:58:12 +08:00
if ( ! PCNTL_G ( spares ) ) {
/* since calling malloc() from within a signal handler is not portable,
* pre - allocate a few records for recording signals */
int i ;
2015-08-05 22:42:42 +08:00
for ( i = 0 ; i < NSIG ; i + + ) {
2005-05-07 22:58:12 +08:00
struct php_pcntl_pending_signal * psig ;
psig = emalloc ( sizeof ( * psig ) ) ;
psig - > next = PCNTL_G ( spares ) ;
PCNTL_G ( spares ) = psig ;
}
}
2019-01-14 20:04:37 +08:00
/* If restart_syscalls was not explicitly specified and the signal is SIGALRM, then default
* restart_syscalls to false . PHP used to enforce that restart_syscalls is false for SIGALRM ,
* so we keep this differing default to reduce the degree of BC breakage . */
if ( restart_syscalls_is_null & & signo = = SIGALRM ) {
restart_syscalls = 0 ;
}
2001-06-12 16:54:25 +08:00
/* Special long value case for SIG_DFL and SIG_IGN */
2014-08-26 01:24:55 +08:00
if ( Z_TYPE_P ( handle ) = = IS_LONG ) {
if ( Z_LVAL_P ( handle ) ! = ( zend_long ) SIG_DFL & & Z_LVAL_P ( handle ) ! = ( zend_long ) SIG_IGN ) {
2020-08-18 04:37:20 +08:00
zend_argument_value_error ( 2 , " must be either SIG_DFL or SIG_IGN when an integer value is given " ) ;
RETURN_THROWS ( ) ;
2001-06-12 16:54:25 +08:00
}
2020-04-15 16:37:33 +08:00
if ( php_signal ( signo , ( Sigfunc * ) Z_LVAL_P ( handle ) , ( int ) restart_syscalls ) = = ( void * ) SIG_ERR ) {
2010-11-02 04:10:17 +08:00
PCNTL_G ( last_error ) = errno ;
2014-12-14 06:06:14 +08:00
php_error_docref ( NULL , E_WARNING , " Error assigning signal " ) ;
2002-03-17 06:31:57 +08:00
RETURN_FALSE ;
2001-06-12 16:54:25 +08:00
}
2016-07-03 00:44:17 +08:00
zend_hash_index_update ( & PCNTL_G ( php_signal_table ) , signo , handle ) ;
2001-06-12 16:54:25 +08:00
RETURN_TRUE ;
2002-03-17 06:31:57 +08:00
}
2015-01-03 17:22:58 +08:00
2019-12-18 03:03:42 +08:00
if ( ! zend_is_callable_ex ( handle , NULL , 0 , NULL , NULL , & error ) ) {
2017-06-26 00:45:59 +08:00
zend_string * func_name = zend_get_callable_name ( handle ) ;
2010-11-02 04:10:17 +08:00
PCNTL_G ( last_error ) = EINVAL ;
2020-08-18 04:37:20 +08:00
zend_argument_type_error ( 2 , " must be of type callable|int, %s given " , zend_zval_type_name ( handle ) ) ;
2018-05-28 21:27:12 +08:00
zend_string_release_ex ( func_name , 0 ) ;
2019-12-18 03:03:42 +08:00
efree ( error ) ;
2020-08-18 04:37:20 +08:00
RETURN_THROWS ( ) ;
2001-06-12 16:54:25 +08:00
}
2019-12-18 03:03:42 +08:00
ZEND_ASSERT ( ! error ) ;
2015-01-03 17:22:58 +08:00
2002-08-22 12:20:10 +08:00
/* Add the function name to our signal table */
2018-06-01 16:58:57 +08:00
handle = zend_hash_index_update ( & PCNTL_G ( php_signal_table ) , signo , handle ) ;
Z_TRY_ADDREF_P ( handle ) ;
2015-01-03 17:22:58 +08:00
2020-04-15 16:37:33 +08:00
if ( php_signal4 ( signo , pcntl_signal_handler , ( int ) restart_syscalls , 1 ) = = ( void * ) SIG_ERR ) {
2010-11-02 04:10:17 +08:00
PCNTL_G ( last_error ) = errno ;
2014-12-14 06:06:14 +08:00
php_error_docref ( NULL , E_WARNING , " Error assigning signal " ) ;
2002-08-22 12:20:10 +08:00
RETURN_FALSE ;
2001-06-12 16:54:25 +08:00
}
2002-03-17 06:31:57 +08:00
RETURN_TRUE ;
2001-06-12 16:54:25 +08:00
}
/* }}} */
2020-07-01 21:32:55 +08:00
/* {{{ Gets signal handler */
2016-07-03 00:44:17 +08:00
PHP_FUNCTION ( pcntl_signal_get_handler )
{
zval * prev_handle ;
zend_long signo ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " l " , & signo ) = = FAILURE ) {
2019-12-31 18:27:02 +08:00
RETURN_THROWS ( ) ;
2016-07-03 00:44:17 +08:00
}
if ( signo < 1 | | signo > 32 ) {
2020-08-18 04:37:20 +08:00
zend_argument_value_error ( 1 , " must be between 1 and 32 " ) ;
RETURN_THROWS ( ) ;
2016-07-03 00:44:17 +08:00
}
if ( ( prev_handle = zend_hash_index_find ( & PCNTL_G ( php_signal_table ) , signo ) ) ! = NULL ) {
2020-01-20 17:34:17 +08:00
RETURN_COPY ( prev_handle ) ;
2016-07-03 00:44:17 +08:00
} else {
2016-07-06 20:54:51 +08:00
RETURN_LONG ( ( zend_long ) SIG_DFL ) ;
2016-07-03 00:44:17 +08:00
}
}
2020-07-01 21:32:55 +08:00
/* {{{ Dispatch signals to signal handlers */
2008-07-30 00:46:11 +08:00
PHP_FUNCTION ( pcntl_signal_dispatch )
{
2019-08-27 23:25:19 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
2019-12-31 18:27:02 +08:00
RETURN_THROWS ( ) ;
2019-08-27 23:25:19 +08:00
}
2008-07-30 00:46:11 +08:00
pcntl_signal_dispatch ( ) ;
RETURN_TRUE ;
}
/* }}} */
2008-07-30 00:59:10 +08:00
# ifdef HAVE_SIGPROCMASK
2020-07-01 21:32:55 +08:00
/* {{{ Examine and change blocked signals */
2008-07-30 00:59:10 +08:00
PHP_FUNCTION ( pcntl_sigprocmask )
{
2014-08-26 01:24:55 +08:00
zend_long how , signo ;
2014-05-06 18:23:56 +08:00
zval * user_set , * user_oldset = NULL , * user_signo ;
2008-11-10 13:57:18 +08:00
sigset_t set , oldset ;
2008-07-30 00:59:10 +08:00
2019-01-07 19:28:51 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " la|z " , & how , & user_set , & user_oldset ) = = FAILURE ) {
2019-12-31 18:27:02 +08:00
RETURN_THROWS ( ) ;
2008-07-30 00:59:10 +08:00
}
2008-11-10 13:57:18 +08:00
if ( sigemptyset ( & set ) ! = 0 | | sigemptyset ( & oldset ) ! = 0 ) {
2010-11-02 04:10:17 +08:00
PCNTL_G ( last_error ) = errno ;
2014-12-14 06:06:14 +08:00
php_error_docref ( NULL , E_WARNING , " %s " , strerror ( errno ) ) ;
2008-07-30 00:59:10 +08:00
RETURN_FALSE ;
}
2014-05-28 21:30:05 +08:00
ZEND_HASH_FOREACH_VAL ( Z_ARRVAL_P ( user_set ) , user_signo ) {
2015-09-29 16:17:43 +08:00
signo = zval_get_long ( user_signo ) ;
2008-07-30 00:59:10 +08:00
if ( sigaddset ( & set , signo ) ! = 0 ) {
2010-11-02 04:10:17 +08:00
PCNTL_G ( last_error ) = errno ;
2014-12-14 06:06:14 +08:00
php_error_docref ( NULL , E_WARNING , " %s " , strerror ( errno ) ) ;
2008-07-30 00:59:10 +08:00
RETURN_FALSE ;
}
2014-05-28 21:30:05 +08:00
} ZEND_HASH_FOREACH_END ( ) ;
2008-07-30 00:59:10 +08:00
2008-11-10 13:57:18 +08:00
if ( sigprocmask ( how , & set , & oldset ) ! = 0 ) {
2010-11-02 04:10:17 +08:00
PCNTL_G ( last_error ) = errno ;
2014-12-14 06:06:14 +08:00
php_error_docref ( NULL , E_WARNING , " %s " , strerror ( errno ) ) ;
2008-07-30 00:59:10 +08:00
RETURN_FALSE ;
}
2008-11-10 13:57:18 +08:00
if ( user_oldset ! = NULL ) {
2019-01-07 19:28:51 +08:00
user_oldset = zend_try_array_init ( user_oldset ) ;
if ( ! user_oldset ) {
2020-01-04 03:44:29 +08:00
RETURN_THROWS ( ) ;
2008-11-10 13:57:18 +08:00
}
2019-01-07 19:28:51 +08:00
2015-08-05 22:42:42 +08:00
for ( signo = 1 ; signo < NSIG ; + + signo ) {
2008-11-10 13:57:18 +08:00
if ( sigismember ( & oldset , signo ) ! = 1 ) {
continue ;
}
2014-08-26 01:24:55 +08:00
add_next_index_long ( user_oldset , signo ) ;
2008-11-10 13:57:18 +08:00
}
}
2008-07-30 00:59:10 +08:00
RETURN_TRUE ;
}
/* }}} */
# endif
2016-06-14 06:33:19 +08:00
# ifdef HAVE_STRUCT_SIGINFO_T
2020-05-20 19:59:44 +08:00
# if defined(HAVE_SIGWAITINFO) && defined(HAVE_SIGTIMEDWAIT)
2008-07-30 00:59:10 +08:00
static void pcntl_sigwaitinfo ( INTERNAL_FUNCTION_PARAMETERS , int timedwait ) /* { { { */
{
2014-05-06 18:23:56 +08:00
zval * user_set , * user_signo , * user_siginfo = NULL ;
2014-08-26 01:24:55 +08:00
zend_long tv_sec = 0 , tv_nsec = 0 ;
2008-07-30 00:59:10 +08:00
sigset_t set ;
int signo ;
siginfo_t siginfo ;
struct timespec timeout ;
if ( timedwait ) {
2019-01-07 19:28:51 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " a|zll " , & user_set , & user_siginfo , & tv_sec , & tv_nsec ) = = FAILURE ) {
2019-12-31 18:27:02 +08:00
RETURN_THROWS ( ) ;
2008-07-30 00:59:10 +08:00
}
} else {
2019-01-07 19:28:51 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " a|z " , & user_set , & user_siginfo ) = = FAILURE ) {
2019-12-31 18:27:02 +08:00
RETURN_THROWS ( ) ;
2008-07-30 00:59:10 +08:00
}
}
if ( sigemptyset ( & set ) ! = 0 ) {
2010-11-02 04:10:17 +08:00
PCNTL_G ( last_error ) = errno ;
2014-12-14 06:06:14 +08:00
php_error_docref ( NULL , E_WARNING , " %s " , strerror ( errno ) ) ;
2008-07-30 00:59:10 +08:00
RETURN_FALSE ;
}
2014-05-28 21:30:05 +08:00
ZEND_HASH_FOREACH_VAL ( Z_ARRVAL_P ( user_set ) , user_signo ) {
2015-09-29 16:17:43 +08:00
signo = zval_get_long ( user_signo ) ;
2008-07-30 00:59:10 +08:00
if ( sigaddset ( & set , signo ) ! = 0 ) {
2010-11-02 04:10:17 +08:00
PCNTL_G ( last_error ) = errno ;
2014-12-14 06:06:14 +08:00
php_error_docref ( NULL , E_WARNING , " %s " , strerror ( errno ) ) ;
2008-07-30 00:59:10 +08:00
RETURN_FALSE ;
}
2014-05-28 21:30:05 +08:00
} ZEND_HASH_FOREACH_END ( ) ;
2008-07-30 00:59:10 +08:00
if ( timedwait ) {
timeout . tv_sec = ( time_t ) tv_sec ;
timeout . tv_nsec = tv_nsec ;
signo = sigtimedwait ( & set , & siginfo , & timeout ) ;
} else {
signo = sigwaitinfo ( & set , & siginfo ) ;
}
if ( signo = = - 1 & & errno ! = EAGAIN ) {
2010-11-02 04:10:17 +08:00
PCNTL_G ( last_error ) = errno ;
2014-12-14 06:06:14 +08:00
php_error_docref ( NULL , E_WARNING , " %s " , strerror ( errno ) ) ;
2008-07-30 00:59:10 +08:00
}
2009-03-28 11:21:04 +08:00
/*
2015-01-03 17:22:58 +08:00
* sigtimedwait and sigwaitinfo can return 0 on success on some
2009-03-28 11:21:04 +08:00
* platforms , e . g . NetBSD
*/
if ( ! signo & & siginfo . si_signo ) {
signo = siginfo . si_signo ;
}
2016-06-14 06:33:19 +08:00
pcntl_siginfo_to_zval ( signo , & siginfo , user_siginfo ) ;
RETURN_LONG ( signo ) ;
}
/* }}} */
2020-07-01 21:32:55 +08:00
/* {{{ Synchronously wait for queued signals */
2016-06-14 06:33:19 +08:00
PHP_FUNCTION ( pcntl_sigwaitinfo )
{
pcntl_sigwaitinfo ( INTERNAL_FUNCTION_PARAM_PASSTHRU , 0 ) ;
}
/* }}} */
2020-07-01 21:32:55 +08:00
/* {{{ Wait for queued signals */
2016-06-14 06:33:19 +08:00
PHP_FUNCTION ( pcntl_sigtimedwait )
{
pcntl_sigwaitinfo ( INTERNAL_FUNCTION_PARAM_PASSTHRU , 1 ) ;
}
/* }}} */
# endif
2009-03-28 11:21:04 +08:00
2016-06-14 06:33:19 +08:00
static void pcntl_siginfo_to_zval ( int signo , siginfo_t * siginfo , zval * user_siginfo ) /* { { { */
{
2008-07-30 00:59:10 +08:00
if ( signo > 0 & & user_siginfo ) {
2019-01-07 19:28:51 +08:00
user_siginfo = zend_try_array_init ( user_siginfo ) ;
if ( ! user_siginfo ) {
return ;
2008-07-30 00:59:10 +08:00
}
2019-01-07 19:28:51 +08:00
2016-06-14 06:33:19 +08:00
add_assoc_long_ex ( user_siginfo , " signo " , sizeof ( " signo " ) - 1 , siginfo - > si_signo ) ;
add_assoc_long_ex ( user_siginfo , " errno " , sizeof ( " errno " ) - 1 , siginfo - > si_errno ) ;
add_assoc_long_ex ( user_siginfo , " code " , sizeof ( " code " ) - 1 , siginfo - > si_code ) ;
2008-07-30 00:59:10 +08:00
switch ( signo ) {
# ifdef SIGCHLD
case SIGCHLD :
2016-06-14 06:33:19 +08:00
add_assoc_long_ex ( user_siginfo , " status " , sizeof ( " status " ) - 1 , siginfo - > si_status ) ;
2008-08-05 23:12:19 +08:00
# ifdef si_utime
2016-06-14 06:33:19 +08:00
add_assoc_double_ex ( user_siginfo , " utime " , sizeof ( " utime " ) - 1 , siginfo - > si_utime ) ;
2008-08-05 23:12:19 +08:00
# endif
# ifdef si_stime
2016-06-14 06:33:19 +08:00
add_assoc_double_ex ( user_siginfo , " stime " , sizeof ( " stime " ) - 1 , siginfo - > si_stime ) ;
2008-08-05 23:12:19 +08:00
# endif
2016-06-14 06:33:19 +08:00
add_assoc_long_ex ( user_siginfo , " pid " , sizeof ( " pid " ) - 1 , siginfo - > si_pid ) ;
add_assoc_long_ex ( user_siginfo , " uid " , sizeof ( " uid " ) - 1 , siginfo - > si_uid ) ;
break ;
case SIGUSR1 :
case SIGUSR2 :
add_assoc_long_ex ( user_siginfo , " pid " , sizeof ( " pid " ) - 1 , siginfo - > si_pid ) ;
add_assoc_long_ex ( user_siginfo , " uid " , sizeof ( " uid " ) - 1 , siginfo - > si_uid ) ;
2008-07-30 00:59:10 +08:00
break ;
# endif
case SIGILL :
case SIGFPE :
case SIGSEGV :
case SIGBUS :
2016-06-14 06:33:19 +08:00
add_assoc_double_ex ( user_siginfo , " addr " , sizeof ( " addr " ) - 1 , ( zend_long ) siginfo - > si_addr ) ;
2008-07-30 00:59:10 +08:00
break ;
# ifdef SIGPOLL
case SIGPOLL :
2016-06-14 06:33:19 +08:00
add_assoc_long_ex ( user_siginfo , " band " , sizeof ( " band " ) - 1 , siginfo - > si_band ) ;
2008-08-05 23:12:19 +08:00
# ifdef si_fd
2016-06-14 06:33:19 +08:00
add_assoc_long_ex ( user_siginfo , " fd " , sizeof ( " fd " ) - 1 , siginfo - > si_fd ) ;
2008-08-05 23:12:19 +08:00
# endif
2008-07-30 00:59:10 +08:00
break ;
# endif
}
2018-06-28 02:25:11 +08:00
# if defined(SIGRTMIN) && defined(SIGRTMAX)
if ( SIGRTMIN < = signo & & signo < = SIGRTMAX ) {
add_assoc_long_ex ( user_siginfo , " pid " , sizeof ( " pid " ) - 1 , siginfo - > si_pid ) ;
add_assoc_long_ex ( user_siginfo , " uid " , sizeof ( " uid " ) - 1 , siginfo - > si_uid ) ;
}
# endif
2008-07-30 00:59:10 +08:00
}
}
/* }}} */
# endif
2003-02-18 09:41:06 +08:00
# ifdef HAVE_GETPRIORITY
2020-07-01 21:32:55 +08:00
/* {{{ Get the priority of any process */
2003-02-18 09:41:06 +08:00
PHP_FUNCTION ( pcntl_getpriority )
{
2014-08-26 01:24:55 +08:00
zend_long who = PRIO_PROCESS ;
2020-06-08 17:10:56 +08:00
zend_long pid ;
2021-01-15 19:30:54 +08:00
bool pid_is_null = 1 ;
2003-02-18 09:41:06 +08:00
int pri ;
2015-01-03 17:22:58 +08:00
2020-08-13 22:32:43 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " |l!l " , & pid , & pid_is_null , & who ) = = FAILURE ) {
2019-12-31 18:27:02 +08:00
RETURN_THROWS ( ) ;
2003-02-18 09:41:06 +08:00
}
2015-01-03 17:22:58 +08:00
/* needs to be cleared, since any returned value is valid */
2003-02-18 09:41:06 +08:00
errno = 0 ;
2020-06-08 17:10:56 +08:00
pri = getpriority ( who , pid_is_null ? getpid ( ) : pid ) ;
2003-02-18 09:41:06 +08:00
if ( errno ) {
2010-11-02 04:10:17 +08:00
PCNTL_G ( last_error ) = errno ;
2003-02-18 09:41:06 +08:00
switch ( errno ) {
case ESRCH :
2014-12-14 06:06:14 +08:00
php_error_docref ( NULL , E_WARNING , " Error %d: No process was located using the given parameters " , errno ) ;
2003-02-18 09:41:06 +08:00
break ;
case EINVAL :
2020-08-18 04:37:20 +08:00
zend_argument_value_error ( 2 , " must be one of PRIO_PGRP, PRIO_USER, or PRIO_PROCESS " ) ;
RETURN_THROWS ( ) ;
2003-02-18 09:41:06 +08:00
default :
2014-12-14 06:06:14 +08:00
php_error_docref ( NULL , E_WARNING , " Unknown error %d has occurred " , errno ) ;
2003-02-18 09:41:06 +08:00
break ;
}
RETURN_FALSE ;
}
2014-08-26 01:24:55 +08:00
RETURN_LONG ( pri ) ;
2003-02-18 09:41:06 +08:00
}
/* }}} */
# endif
# ifdef HAVE_SETPRIORITY
2020-07-01 21:32:55 +08:00
/* {{{ Change the priority of any process */
2003-02-18 09:41:06 +08:00
PHP_FUNCTION ( pcntl_setpriority )
{
2014-08-26 01:24:55 +08:00
zend_long who = PRIO_PROCESS ;
2020-06-08 17:10:56 +08:00
zend_long pid ;
2021-01-15 19:30:54 +08:00
bool pid_is_null = 1 ;
2014-08-26 01:24:55 +08:00
zend_long pri ;
2003-02-18 09:41:06 +08:00
2020-08-13 22:32:43 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " l|l!l " , & pri , & pid , & pid_is_null , & who ) = = FAILURE ) {
2019-12-31 18:27:02 +08:00
RETURN_THROWS ( ) ;
2003-02-18 09:41:06 +08:00
}
2020-06-08 17:10:56 +08:00
if ( setpriority ( who , pid_is_null ? getpid ( ) : pid , pri ) ) {
2010-11-02 04:10:17 +08:00
PCNTL_G ( last_error ) = errno ;
2003-02-18 09:41:06 +08:00
switch ( errno ) {
case ESRCH :
2014-12-14 06:06:14 +08:00
php_error_docref ( NULL , E_WARNING , " Error %d: No process was located using the given parameters " , errno ) ;
2003-02-18 09:41:06 +08:00
break ;
case EINVAL :
2020-08-18 04:37:20 +08:00
zend_argument_value_error ( 3 , " must be one of PRIO_PGRP, PRIO_USER, or PRIO_PROCESS " ) ;
RETURN_THROWS ( ) ;
2003-02-18 09:41:06 +08:00
case EPERM :
2014-12-14 06:06:14 +08:00
php_error_docref ( NULL , E_WARNING , " Error %d: A process was located, but neither its effective nor real user ID matched the effective user ID of the caller " , errno ) ;
2003-02-18 09:41:06 +08:00
break ;
case EACCES :
2014-12-14 06:06:14 +08:00
php_error_docref ( NULL , E_WARNING , " Error %d: Only a super user may attempt to increase the process priority " , errno ) ;
2003-02-18 09:41:06 +08:00
break ;
default :
2014-12-14 06:06:14 +08:00
php_error_docref ( NULL , E_WARNING , " Unknown error %d has occurred " , errno ) ;
2003-02-18 09:41:06 +08:00
break ;
}
RETURN_FALSE ;
}
2015-01-03 17:22:58 +08:00
2003-02-18 09:41:06 +08:00
RETURN_TRUE ;
}
/* }}} */
# endif
2020-07-01 21:32:55 +08:00
/* {{{ Retrieve the error number set by the last pcntl function which failed. */
2010-11-02 04:10:17 +08:00
PHP_FUNCTION ( pcntl_get_last_error )
{
2019-08-27 23:25:19 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
2019-12-31 18:27:02 +08:00
RETURN_THROWS ( ) ;
2019-08-27 23:25:19 +08:00
}
RETURN_LONG ( PCNTL_G ( last_error ) ) ;
2010-11-02 04:10:17 +08:00
}
/* }}} */
2020-07-01 21:32:55 +08:00
/* {{{ Retrieve the system error message associated with the given errno. */
2010-11-02 04:10:17 +08:00
PHP_FUNCTION ( pcntl_strerror )
{
2019-08-27 23:25:19 +08:00
zend_long error ;
2010-11-02 04:10:17 +08:00
2019-08-27 23:25:19 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " l " , & error ) = = FAILURE ) {
2019-12-31 18:27:02 +08:00
RETURN_THROWS ( ) ;
2019-08-27 23:25:19 +08:00
}
2010-11-02 04:10:17 +08:00
2019-08-27 23:25:19 +08:00
RETURN_STRING ( strerror ( error ) ) ;
2010-11-02 04:10:17 +08:00
}
/* }}} */
2001-06-26 01:56:23 +08:00
/* Our custom signal handler that calls the appropriate php_function */
2016-06-14 06:33:19 +08:00
# ifdef HAVE_STRUCT_SIGINFO_T
static void pcntl_signal_handler ( int signo , siginfo_t * siginfo , void * context )
# else
2001-06-20 05:42:57 +08:00
static void pcntl_signal_handler ( int signo )
2016-06-14 06:33:19 +08:00
# endif
2001-06-20 05:42:57 +08:00
{
2005-05-07 22:58:12 +08:00
struct php_pcntl_pending_signal * psig ;
2015-01-03 17:22:58 +08:00
2005-05-07 22:58:12 +08:00
psig = PCNTL_G ( spares ) ;
if ( ! psig ) {
/* oops, too many signals for us to track, so we'll forget about this one */
return ;
}
PCNTL_G ( spares ) = psig - > next ;
psig - > signo = signo ;
psig - > next = NULL ;
2016-06-14 06:33:19 +08:00
# ifdef HAVE_STRUCT_SIGINFO_T
2017-01-15 10:51:33 +08:00
psig - > siginfo = * siginfo ;
2016-06-14 06:33:19 +08:00
# endif
2005-05-07 22:58:12 +08:00
/* the head check is important, as the tick handler cannot atomically clear both
* the head and tail */
if ( PCNTL_G ( head ) & & PCNTL_G ( tail ) ) {
PCNTL_G ( tail ) - > next = psig ;
} else {
PCNTL_G ( head ) = psig ;
2001-06-20 05:42:57 +08:00
}
2005-05-07 22:58:12 +08:00
PCNTL_G ( tail ) = psig ;
2014-06-11 23:34:34 +08:00
PCNTL_G ( pending_signals ) = 1 ;
2016-07-06 18:11:47 +08:00
if ( PCNTL_G ( async_signals ) ) {
EG ( vm_interrupt ) = 1 ;
}
2001-06-20 05:42:57 +08:00
}
2008-07-30 00:46:11 +08:00
void pcntl_signal_dispatch ( )
2001-07-30 16:24:42 +08:00
{
2016-06-14 06:33:19 +08:00
zval params [ 2 ] , * handle , retval ;
2005-05-07 22:58:12 +08:00
struct php_pcntl_pending_signal * queue , * next ;
2010-11-02 06:29:25 +08:00
sigset_t mask ;
sigset_t old_mask ;
2014-06-11 23:34:34 +08:00
if ( ! PCNTL_G ( pending_signals ) ) {
return ;
}
2015-01-03 17:22:58 +08:00
2010-11-02 06:29:25 +08:00
/* Mask all signals */
sigfillset ( & mask ) ;
sigprocmask ( SIG_BLOCK , & mask , & old_mask ) ;
2001-06-20 05:42:57 +08:00
2016-06-14 06:33:19 +08:00
/* Bail if the queue is empty or if we are already playing the queue */
if ( ! PCNTL_G ( head ) | | PCNTL_G ( processing_signal_queue ) ) {
2010-11-02 06:40:29 +08:00
sigprocmask ( SIG_SETMASK , & old_mask , NULL ) ;
2001-06-20 05:42:57 +08:00
return ;
2010-11-02 06:40:29 +08:00
}
2001-06-20 05:42:57 +08:00
2002-08-22 12:20:10 +08:00
/* Prevent reentrant handler calls */
2002-03-17 06:31:57 +08:00
PCNTL_G ( processing_signal_queue ) = 1 ;
2005-05-07 22:58:12 +08:00
queue = PCNTL_G ( head ) ;
PCNTL_G ( head ) = NULL ; /* simple stores are atomic */
2015-01-03 17:22:58 +08:00
2001-06-20 05:42:57 +08:00
/* Allocate */
2005-05-07 22:58:12 +08:00
while ( queue ) {
2014-05-06 18:23:56 +08:00
if ( ( handle = zend_hash_index_find ( & PCNTL_G ( php_signal_table ) , queue - > signo ) ) ! = NULL ) {
2016-07-06 20:45:20 +08:00
if ( Z_TYPE_P ( handle ) ! = IS_LONG ) {
ZVAL_NULL ( & retval ) ;
2016-06-14 06:33:19 +08:00
ZVAL_LONG ( & params [ 0 ] , queue - > signo ) ;
# ifdef HAVE_STRUCT_SIGINFO_T
2017-01-15 10:51:33 +08:00
array_init ( & params [ 1 ] ) ;
pcntl_siginfo_to_zval ( queue - > signo , & queue - > siginfo , & params [ 1 ] ) ;
2016-06-14 06:33:19 +08:00
# else
ZVAL_NULL ( & params [ 1 ] ) ;
# endif
2016-07-06 20:45:20 +08:00
/* Call php signal handler - Note that we do not report errors, and we ignore the return value */
/* FIXME: this is probably broken when multiple signals are handled in this while loop (retval) */
2019-03-10 15:16:04 +08:00
call_user_function ( NULL , NULL , handle , & retval , 2 , params ) ;
2016-07-06 20:45:20 +08:00
zval_ptr_dtor ( & retval ) ;
2018-05-29 22:58:06 +08:00
# ifdef HAVE_STRUCT_SIGINFO_T
2016-06-14 06:33:19 +08:00
zval_ptr_dtor ( & params [ 1 ] ) ;
2018-05-29 22:58:06 +08:00
# endif
2016-07-06 20:45:20 +08:00
}
2001-06-20 05:42:57 +08:00
}
2002-05-07 07:01:46 +08:00
2005-05-07 22:58:12 +08:00
next = queue - > next ;
queue - > next = PCNTL_G ( spares ) ;
PCNTL_G ( spares ) = queue ;
queue = next ;
2001-06-20 05:42:57 +08:00
}
2014-06-11 23:34:34 +08:00
PCNTL_G ( pending_signals ) = 0 ;
2001-06-20 05:42:57 +08:00
/* Re-enable queue */
2002-03-17 06:31:57 +08:00
PCNTL_G ( processing_signal_queue ) = 0 ;
2015-01-03 17:22:58 +08:00
2010-11-02 06:29:25 +08:00
/* return signal mask to previous state */
sigprocmask ( SIG_SETMASK , & old_mask , NULL ) ;
2001-06-20 05:42:57 +08:00
}
2020-07-01 21:32:55 +08:00
/* {{{ Enable/disable asynchronous signal handling and return the old setting. */
2016-07-06 18:11:47 +08:00
PHP_FUNCTION ( pcntl_async_signals )
{
2021-01-15 19:30:54 +08:00
bool on , on_is_null = 1 ;
2005-05-07 22:58:12 +08:00
2020-06-08 17:10:56 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " |b! " , & on , & on_is_null ) = = FAILURE ) {
2019-12-31 18:27:02 +08:00
RETURN_THROWS ( ) ;
2016-07-06 18:11:47 +08:00
}
2020-06-08 17:10:56 +08:00
if ( on_is_null ) {
RETURN_BOOL ( PCNTL_G ( async_signals ) ) ;
}
2016-07-06 18:11:47 +08:00
RETVAL_BOOL ( PCNTL_G ( async_signals ) ) ;
PCNTL_G ( async_signals ) = on ;
}
/* }}} */
2019-01-22 07:56:43 +08:00
# ifdef HAVE_UNSHARE
2020-07-01 21:32:55 +08:00
/* {{{ disassociate parts of the process execution context */
2019-01-22 07:56:43 +08:00
PHP_FUNCTION ( pcntl_unshare )
{
zend_long flags ;
ZEND_PARSE_PARAMETERS_START ( 1 , 1 )
Z_PARAM_LONG ( flags )
ZEND_PARSE_PARAMETERS_END ( ) ;
2020-08-18 04:37:20 +08:00
if ( unshare ( flags ) = = - 1 ) {
2019-01-22 07:56:43 +08:00
PCNTL_G ( last_error ) = errno ;
switch ( errno ) {
# ifdef EINVAL
case EINVAL :
2020-08-18 04:37:20 +08:00
zend_argument_value_error ( 1 , " must be a combination of CLONE_* flags " ) ;
RETURN_THROWS ( ) ;
2019-01-22 07:56:43 +08:00
break ;
# endif
# ifdef ENOMEM
case ENOMEM :
php_error_docref ( NULL , E_WARNING , " Error %d: Insufficient memory for unshare " , errno ) ;
break ;
# endif
# ifdef EPERM
case EPERM :
php_error_docref ( NULL , E_WARNING , " Error %d: No privilege to use these flags " , errno ) ;
break ;
# endif
# ifdef ENOSPC
case ENOSPC :
php_error_docref ( NULL , E_WARNING , " Error %d: Reached the maximum nesting limit for one of the specified namespaces " , errno ) ;
break ;
# endif
# ifdef EUSERS
case EUSERS :
php_error_docref ( NULL , E_WARNING , " Error %d: Reached the maximum nesting limit for the user namespace " , errno ) ;
break ;
# endif
default :
php_error_docref ( NULL , E_WARNING , " Unknown error %d has occurred " , errno ) ;
break ;
}
RETURN_FALSE ;
}
RETURN_TRUE ;
}
/* }}} */
# endif
2016-07-06 18:11:47 +08:00
static void pcntl_interrupt_function ( zend_execute_data * execute_data )
{
pcntl_signal_dispatch ( ) ;
if ( orig_interrupt_function ) {
orig_interrupt_function ( execute_data ) ;
}
}