Skip to content

Commit 28382aa

Browse files
devnexenkrakjoe
authored andcommitted
pcntl: Adding pcntl_rfork support.
1 parent 20ef668 commit 28382aa

File tree

7 files changed

+144
-1
lines changed

7 files changed

+144
-1
lines changed

Diff for: UPGRADING

+3
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,9 @@ PHP 8.1 UPGRADE NOTES
346346
. Added array_is_list(array $array), which will return true if the array keys are 0 .. count($array)-1 in that order.
347347
RFC: https://wiki.php.net/rfc/is_list
348348

349+
- pcntl:
350+
. Added pcntl_rfork for FreeBSD variants
351+
349352
- Reflection:
350353
. Added ReflectionFunctionAbstract::getClosureUsedVariables
351354

Diff for: ext/pcntl/config.m4

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ if test "$PHP_PCNTL" != "no"; then
77
AC_CHECK_FUNCS([fork], [], [AC_MSG_ERROR([pcntl: fork() not supported by this platform])])
88
AC_CHECK_FUNCS([waitpid], [], [AC_MSG_ERROR([pcntl: waitpid() not supported by this platform])])
99
AC_CHECK_FUNCS([sigaction], [], [AC_MSG_ERROR([pcntl: sigaction() not supported by this platform])])
10-
AC_CHECK_FUNCS([getpriority setpriority wait3 wait4 sigwaitinfo sigtimedwait unshare])
10+
AC_CHECK_FUNCS([getpriority setpriority wait3 wait4 sigwaitinfo sigtimedwait unshare rfork])
1111

1212
AC_MSG_CHECKING([for siginfo_t])
1313
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[

Diff for: ext/pcntl/pcntl.c

+78
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,36 @@ void php_register_signal_constants(INIT_FUNC_ARGS)
340340
REGISTER_LONG_CONSTANT("CLONE_NEWCGROUP", CLONE_NEWCGROUP, CONST_CS | CONST_PERSISTENT);
341341
#endif
342342
#endif
343+
344+
#ifdef HAVE_RFORK
345+
#ifdef RFPROC
346+
REGISTER_LONG_CONSTANT("RFPROC", RFPROC, CONST_CS | CONST_PERSISTENT);
347+
#endif
348+
#ifdef RFNOWAIT
349+
REGISTER_LONG_CONSTANT("RFNOWAIT", RFNOWAIT, CONST_CS | CONST_PERSISTENT);
350+
#endif
351+
#ifdef RFCFDG
352+
REGISTER_LONG_CONSTANT("RFCFDG", RFCFDG, CONST_CS | CONST_PERSISTENT);
353+
#endif
354+
#ifdef RFFDG
355+
REGISTER_LONG_CONSTANT("RFFDG", RFFDG, CONST_CS | CONST_PERSISTENT);
356+
#endif
357+
#ifdef RFLINUXTHPN
358+
REGISTER_LONG_CONSTANT("RFLINUXTHPN", RFLINUXTHPN, CONST_CS | CONST_PERSISTENT);
359+
#endif
360+
#ifdef RFMEM
361+
REGISTER_LONG_CONSTANT("RFMEM", RFMEM, CONST_CS | CONST_PERSISTENT);
362+
#endif
363+
#ifdef RFSIGSHARE
364+
REGISTER_LONG_CONSTANT("RFSIGSHARE", RFSIGSHARE, CONST_CS | CONST_PERSISTENT);
365+
#endif
366+
#ifdef RFSIGZMB
367+
REGISTER_LONG_CONSTANT("RFSIGSZMB", RFSIGSZMB, CONST_CS | CONST_PERSISTENT);
368+
#endif
369+
#ifdef RFTHREAD
370+
REGISTER_LONG_CONSTANT("RFTHREAD", RFTHREAD, CONST_CS | CONST_PERSISTENT);
371+
#endif
372+
#endif
343373
}
344374

345375
static void php_pcntl_register_errno_constants(INIT_FUNC_ARGS)
@@ -1468,6 +1498,54 @@ PHP_FUNCTION(pcntl_unshare)
14681498
/* }}} */
14691499
#endif
14701500

1501+
#ifdef HAVE_RFORK
1502+
/* {{{ proto bool pcntl_rfork([int flags|custom signal)
1503+
More control over the process creation is given over fork/vfork. */
1504+
PHP_FUNCTION(pcntl_rfork)
1505+
{
1506+
zend_long flags;
1507+
zend_long csignal;
1508+
pid_t pid;
1509+
1510+
ZEND_PARSE_PARAMETERS_START(1, 2)
1511+
Z_PARAM_LONG(flags)
1512+
Z_PARAM_OPTIONAL
1513+
Z_PARAM_LONG(csignal)
1514+
ZEND_PARSE_PARAMETERS_END();
1515+
1516+
/* This is a flag to use with great caution in general, preferably not within PHP */
1517+
if ((flags & RFMEM) != 0) {
1518+
flags &= ~RFMEM;
1519+
}
1520+
1521+
/* A new pid is required */
1522+
flags |= RFPROC;
1523+
1524+
if (ZEND_NUM_ARGS() == 2 && (flags & RFTSIGZMB) != 0) {
1525+
flags |= RFTSIGFLAGS(csignal);
1526+
}
1527+
1528+
pid = rfork(flags);
1529+
1530+
if (pid == -1) {
1531+
PCNTL_G(last_error) = errno;
1532+
switch (errno) {
1533+
case EINVAL:
1534+
php_error_docref(NULL, E_WARNING, "RFFDG and RFCFDG modes are mutually exclusive");
1535+
break;
1536+
case EAGAIN:
1537+
php_error_docref(NULL, E_WARNING, "Maximum process creations limit reached\n");
1538+
break;
1539+
default:
1540+
php_error_docref(NULL, E_WARNING, "Error %d", errno);
1541+
}
1542+
}
1543+
1544+
RETURN_LONG((zend_long) pid);
1545+
}
1546+
#endif
1547+
/* }}} */
1548+
14711549
static void pcntl_interrupt_function(zend_execute_data *execute_data)
14721550
{
14731551
pcntl_signal_dispatch();

Diff for: ext/pcntl/pcntl.stub.php

+4
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,7 @@ function pcntl_async_signals(?bool $enable = null): bool {}
7979
#ifdef HAVE_UNSHARE
8080
function pcntl_unshare(int $flags): bool {}
8181
#endif
82+
83+
#ifdef HAVE_RFORK
84+
function pcntl_rfork(int $flags, int $signal): int{}
85+
#endif

Diff for: ext/pcntl/pcntl_arginfo.h

+10
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,13 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pcntl_unshare, 0, 1, _IS_BOOL, 0
119119
ZEND_END_ARG_INFO()
120120
#endif
121121

122+
#if defined(HAVE_RFORK)
123+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pcntl_rfork, 0, 1, IS_LONG, 0)
124+
ZEND_ARG_TYPE_INFO(0, flags, IS_LONG, 0)
125+
ZEND_ARG_TYPE_INFO(0, signal, IS_LONG, 0)
126+
ZEND_END_ARG_INFO()
127+
#endif
128+
122129

123130
ZEND_FUNCTION(pcntl_fork);
124131
ZEND_FUNCTION(pcntl_waitpid);
@@ -158,6 +165,9 @@ ZEND_FUNCTION(pcntl_async_signals);
158165
#if defined(HAVE_UNSHARE)
159166
ZEND_FUNCTION(pcntl_unshare);
160167
#endif
168+
#if defined(HAVE_RFORK)
169+
ZEND_FUNCTION(pcntl_rfork);
170+
#endif
161171

162172

163173
static const zend_function_entry ext_functions[] = {

Diff for: ext/pcntl/tests/pcntl_rfork.phpt

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
Test function pcntl_rfork() with no flag.
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('pcntl')) die('skip pcntl extension not available');
6+
elseif (!extension_loaded('posix')) die('skip posix extension not available');
7+
if (!function_exists('pcntl_rfork')) die('skip pcntl_rfork unavailable');
8+
?>
9+
--FILE--
10+
<?php
11+
echo "*** Test with no flags ***\n";
12+
13+
$pid = pcntl_rfork(0);
14+
if ($pid > 0) {
15+
pcntl_wait($status);
16+
var_dump($pid);
17+
} else {
18+
var_dump($pid);
19+
}
20+
?>
21+
--EXPECTF--
22+
*** Test with no flags ***
23+
int(0)
24+
int(%d)

Diff for: ext/pcntl/tests/pcntl_rfork_nowait.phpt

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
Test function pcntl_rfork() with no wait flag.
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('pcntl')) die('skip pcntl extension not available');
6+
elseif (!extension_loaded('posix')) die('skip posix extension not available');
7+
if (!function_exists('pcntl_rfork')) die('skip pcntl_rfork unavailable');
8+
?>
9+
--FILE--
10+
<?php
11+
echo "*** Test by with child not reporting to the parent ***\n";
12+
13+
$pid = pcntl_rfork(RFNOWAIT|RFTSIGZMB,SIGUSR1);
14+
if ($pid > 0) {
15+
var_dump($pid);
16+
} else {
17+
var_dump($pid);
18+
sleep(1);
19+
}
20+
?>
21+
--EXPECTF--
22+
*** Test by with child not reporting to the parent ***
23+
int(%d)
24+
int(0)

0 commit comments

Comments
 (0)