Skip to content

Commit 007046f

Browse files
devnexenkrakjoe
authored andcommitted
pcntl_rfork: following-up suggestions.
removing RFMEM constant. treating beforehand the only case where rfork would return EINVAL.
1 parent 643f3c2 commit 007046f

File tree

5 files changed

+131
-53
lines changed

5 files changed

+131
-53
lines changed

ext/pcntl/pcntl.c

Lines changed: 50 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -357,12 +357,6 @@ void php_register_signal_constants(INIT_FUNC_ARGS)
357357
#ifdef RFLINUXTHPN
358358
REGISTER_LONG_CONSTANT("RFLINUXTHPN", RFLINUXTHPN, CONST_CS | CONST_PERSISTENT);
359359
#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
366360
#ifdef RFTSIGZMB
367361
REGISTER_LONG_CONSTANT("RFTSIGZMB", RFTSIGZMB, CONST_CS | CONST_PERSISTENT);
368362
#endif
@@ -1503,45 +1497,56 @@ PHP_FUNCTION(pcntl_unshare)
15031497
More control over the process creation is given over fork/vfork. */
15041498
PHP_FUNCTION(pcntl_rfork)
15051499
{
1506-
zend_long flags;
1507-
zend_long csignal = 0;
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 ((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);
1500+
zend_long flags;
1501+
zend_long csignal = 0;
1502+
pid_t pid;
1503+
1504+
ZEND_PARSE_PARAMETERS_START(1, 2)
1505+
Z_PARAM_LONG(flags)
1506+
Z_PARAM_OPTIONAL
1507+
Z_PARAM_LONG(csignal)
1508+
ZEND_PARSE_PARAMETERS_END();
1509+
1510+
/* This is a flag to use with great caution in general, preferably not within PHP */
1511+
if ((flags & RFMEM) != 0) {
1512+
zend_argument_value_error(1, "must not include RFMEM value, not allowed within this context");
1513+
RETURN_THROWS();
1514+
}
1515+
1516+
if ((flags & RFSIGSHARE) != 0) {
1517+
zend_argument_value_error(1, "must not include RFSIGSHARE value, not allowed within this context");
1518+
RETURN_THROWS();
1519+
}
1520+
1521+
if ((flags & (RFFDG | RFCFDG)) == (RFFDG | RFCFDG)) {
1522+
zend_argument_value_error(1, "must not include both RFFDG and RFCFDG, because these flags are mutually exclusive");
1523+
RETURN_THROWS();
1524+
}
1525+
1526+
/* A new pid is required */
1527+
if (!(flags & (RFPROC))) {
1528+
flags |= RFPROC;
1529+
}
1530+
1531+
if ((flags & RFTSIGZMB) != 0) {
1532+
flags |= RFTSIGFLAGS(csignal);
1533+
}
1534+
1535+
pid = rfork(flags);
1536+
1537+
if (pid == -1) {
1538+
PCNTL_G(last_error) = errno;
1539+
switch (errno) {
1540+
case EAGAIN:
1541+
php_error_docref(NULL, E_WARNING, "Maximum process creations limit reached\n");
1542+
break;
1543+
1544+
default:
1545+
php_error_docref(NULL, E_WARNING, "Error %d", errno);
1546+
}
1547+
}
1548+
1549+
RETURN_LONG((zend_long) pid);
15451550
}
15461551
#endif
15471552
/* }}} */

ext/pcntl/tests/pcntl_rfork.phpt

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,11 @@ Test function pcntl_rfork() with no flag.
1111
echo "*** Test with no flags ***\n";
1212

1313
$pid = pcntl_rfork(0);
14-
if ($pid > 0) {
15-
pcntl_wait($status);
16-
var_dump($pid);
17-
} else {
18-
var_dump($pid);
14+
if ($pid == 0) {
15+
echo "child";
16+
exit;
1917
}
2018
?>
2119
--EXPECTF--
2220
*** Test with no flags ***
23-
int(0)
24-
int(%d)
21+
child
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
--TEST--
2+
Test function pcntl_rfork() with wrong flags
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 "\n*** Test with RFMEM ***\n";
12+
try {
13+
$pid = pcntl_rfork(32);
14+
} catch (ValueError $e) {
15+
echo $e;
16+
}
17+
echo "\n*** Test with RFSIGSHARE ***\n";
18+
try {
19+
$pid = pcntl_rfork(16384);
20+
} catch (ValueError $e) {
21+
echo $e;
22+
}
23+
echo "\n*** Test with RFFDG|RFCFDG ***\n";
24+
try {
25+
$pid = pcntl_rfork(RFFDG|RFCFDG);
26+
} catch (ValueError $e) {
27+
echo $e;
28+
}
29+
?>
30+
--EXPECTF--
31+
*** Test with RFMEM ***
32+
ValueError: pcntl_rfork(): Argument #1 ($flags) must not include RFMEM value, not allowed within this context in %s
33+
Stack trace:
34+
#0 %s: pcntl_rfork(32)
35+
#1 {main}
36+
*** Test with RFSIGSHARE ***
37+
ValueError: pcntl_rfork(): Argument #1 ($flags) must not include RFSIGSHARE value, not allowed within this context in %s
38+
Stack trace:
39+
#0 %s: pcntl_rfork(16384)
40+
#1 {main}
41+
*** Test with RFFDG|RFCFDG ***
42+
ValueError: pcntl_rfork(): Argument #1 ($flags) must not include both RFFDG and RFCFDG, because these flags are mutually exclusive in %s
43+
Stack trace:
44+
#0 %s: pcntl_rfork(4100)
45+
#1 {main}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
--TEST--
2+
Test function pcntl_rfork() with RFCFDG and RFFDG flags.
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 "\n*** Test with RFFDG and RFCFDG flags ***\n";
12+
$pid = pcntl_rfork(RFFDG);
13+
if ($pid > 0) {
14+
pcntl_wait($status);
15+
var_dump($pid);
16+
} else {
17+
var_dump($pid);
18+
exit;
19+
}
20+
21+
$pid = pcntl_rfork(RFCFDG);
22+
if ($pid > 0) {
23+
pcntl_wait($status);
24+
var_dump($pid);
25+
}
26+
?>
27+
--EXPECTF--
28+
*** Test with RFFDG and RFCFDG flags ***
29+
int(0)
30+
int(%d)
31+
int(%d)

ext/pcntl/tests/pcntl_rfork_nowait.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ if ($pid > 0) {
1515
var_dump($pid);
1616
} else {
1717
var_dump($pid);
18-
sleep(1);
18+
sleep(2); // as the child does not wait so we see its "pid"
1919
}
2020
?>
2121
--EXPECTF--

0 commit comments

Comments
 (0)