Skip to content

Fix pcntl get/set priority #9044

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 35 additions & 2 deletions ext/pcntl/pcntl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1265,7 +1265,8 @@ PHP_FUNCTION(pcntl_getpriority)
/* needs to be cleared, since any returned value is valid */
errno = 0;

pri = getpriority(who, pid_is_null ? getpid() : pid);
pid = pid_is_null ? getpid() : pid;
pri = getpriority(who, pid);

if (errno) {
PCNTL_G(last_error) = errno;
Expand All @@ -1274,8 +1275,22 @@ PHP_FUNCTION(pcntl_getpriority)
php_error_docref(NULL, E_WARNING, "Error %d: No process was located using the given parameters", errno);
break;
case EINVAL:
#ifdef PRIO_DARWIN_BG
if (who != PRIO_PGRP && who != PRIO_USER && who != PRIO_PROCESS && who != PRIO_DARWIN_THREAD) {
zend_argument_value_error(2, "must be one of PRIO_PGRP, PRIO_USER, PRIO_PROCESS or PRIO_DARWIN_THREAD");
RETURN_THROWS();
} else if (who == PRIO_DARWIN_THREAD && pid != 0) {
zend_argument_value_error(1, "must be 0 (zero) if PRIO_DARWIN_THREAD is provided as second parameter");
RETURN_THROWS();
} else {
zend_argument_value_error(1, "is not a valid process, process group, or user ID");
RETURN_THROWS();
}
#else
zend_argument_value_error(2, "must be one of PRIO_PGRP, PRIO_USER, or PRIO_PROCESS");
RETURN_THROWS();
#endif

default:
php_error_docref(NULL, E_WARNING, "Unknown error %d has occurred", errno);
break;
Expand Down Expand Up @@ -1304,15 +1319,33 @@ PHP_FUNCTION(pcntl_setpriority)
Z_PARAM_LONG(who)
ZEND_PARSE_PARAMETERS_END();

if (setpriority(who, pid_is_null ? getpid() : pid, pri)) {
pid = pid_is_null ? getpid() : pid;

if (setpriority(who, pid, pri)) {
PCNTL_G(last_error) = errno;
switch (errno) {
case ESRCH:
php_error_docref(NULL, E_WARNING, "Error %d: No process was located using the given parameters", errno);
break;
case EINVAL:
#ifdef PRIO_DARWIN_BG
if (who != PRIO_PGRP && who != PRIO_USER && who != PRIO_PROCESS && who != PRIO_DARWIN_THREAD) {
zend_argument_value_error(3, "must be one of PRIO_PGRP, PRIO_USER, PRIO_PROCESS or PRIO_DARWIN_THREAD");
RETURN_THROWS();
} else if (who == PRIO_DARWIN_THREAD && pid != 0) {
zend_argument_value_error(2, "must be 0 (zero) if PRIO_DARWIN_THREAD is provided as second parameter");
RETURN_THROWS();
} else if (who == PRIO_DARWIN_THREAD && pid == 0 && (pri != 0 && pri != PRIO_DARWIN_BG)) {
zend_argument_value_error(1, "must be either 0 (zero) or PRIO_DARWIN_BG, for mode PRIO_DARWIN_THREAD");
RETURN_THROWS();
} else {
zend_argument_value_error(2, "is not a valid process, process group, or user ID");
RETURN_THROWS();
}
#else
zend_argument_value_error(3, "must be one of PRIO_PGRP, PRIO_USER, or PRIO_PROCESS");
RETURN_THROWS();
#endif
case EPERM:
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);
break;
Expand Down
16 changes: 13 additions & 3 deletions ext/pcntl/tests/pcntl_getpriority_error.phpt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
--TEST--
pcntl_getpriority() - Wrong process identifier
pcntl_getpriority() - Wrong mode passed and also for non existing process id provided
--EXTENSIONS--
pcntl
--SKIPIF--
Expand All @@ -8,16 +8,26 @@ pcntl
if (!function_exists('pcntl_getpriority')) {
die('skip pcntl_getpriority doesn\'t exist');
}

if (PHP_OS == "Darwin") {
die("skip This test is not for Darwin");
}

?>
--FILE--
<?php

try {
pcntl_getpriority(null, 42);
pcntl_getpriority(null, PRIO_PGRP + PRIO_USER + PRIO_PROCESS + 10);
} catch (ValueError $exception) {
echo $exception->getMessage() . "\n";
}

// Different behavior in MacOS than rest of operating systems
pcntl_getpriority(-1, PRIO_PROCESS);

?>
--EXPECT--
--EXPECTF--
pcntl_getpriority(): Argument #2 ($mode) must be one of PRIO_PGRP, PRIO_USER, or PRIO_PROCESS

Warning: pcntl_getpriority(): Error %d: No process was located using the given parameters in %s
43 changes: 43 additions & 0 deletions ext/pcntl/tests/pcntl_getpriority_error_darwin.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
--TEST--
pcntl_getpriority() - Wrong mode passed and also for non existing process id provided
--EXTENSIONS--
pcntl
--SKIPIF--
<?php

if (!function_exists('pcntl_getpriority')) {
die('skip pcntl_getpriority doesn\'t exist');
}

if (PHP_OS !== "Darwin") {
die("skip This test only runs on Darwin");
}

?>
--FILE--
<?php

try {
pcntl_getpriority(null, (PRIO_PGRP + PRIO_USER + PRIO_PROCESS + 10));
} catch (ValueError $exception) {
echo $exception->getMessage() . "\n";
}

try {
pcntl_getpriority(-1, PRIO_DARWIN_THREAD);
} catch (ValueError $exception) {
echo $exception->getMessage() . "\n";
}

try {
// Different behavior in MacOS than rest of operating systems
pcntl_getpriority(-1, PRIO_PROCESS);
} catch (ValueError $exception) {
echo $exception->getMessage() . "\n";
}

?>
--EXPECT--
pcntl_getpriority(): Argument #2 ($mode) must be one of PRIO_PGRP, PRIO_USER, PRIO_PROCESS or PRIO_DARWIN_THREAD
pcntl_getpriority(): Argument #1 ($process_id) must be 0 (zero) if PRIO_DARWIN_THREAD is provided as second parameter
pcntl_getpriority(): Argument #1 ($process_id) is not a valid process, process group, or user ID
15 changes: 12 additions & 3 deletions ext/pcntl/tests/pcntl_setpriority_error.phpt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
--TEST--
pcntl_setpriority() - Wrong process identifier
pcntl_setpriority() - Check for errors
--EXTENSIONS--
pcntl
--SKIPIF--
Expand All @@ -8,16 +8,25 @@ pcntl
if (!function_exists('pcntl_setpriority')) {
die('skip pcntl_setpriority doesn\'t exist');
}

if (PHP_OS == "Darwin") {
die("skip This test is not for Darwin");
}

?>
--FILE--
<?php

try {
pcntl_setpriority(0, null, 42);
$result = pcntl_setpriority(0, null, (PRIO_PGRP + PRIO_USER + PRIO_PROCESS + 10));
} catch (ValueError $exception) {
echo $exception->getMessage() . "\n";
}

pcntl_setpriority(0, -123);

?>
--EXPECT--
--EXPECTF--
pcntl_setpriority(): Argument #3 ($mode) must be one of PRIO_PGRP, PRIO_USER, or PRIO_PROCESS

Warning: pcntl_setpriority(): Error 3: No process was located using the given parameters in %s
46 changes: 46 additions & 0 deletions ext/pcntl/tests/pcntl_setpriority_error_darwin.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
--TEST--
pcntl_setpriority() - Check for errors
--EXTENSIONS--
pcntl
--SKIPIF--
<?php

if (!function_exists('pcntl_setpriority')) {
die('skip pcntl_setpriority doesn\'t exist');
}

if (PHP_OS !== "Darwin") {
die("skip This test only runs on Darwin");
}

?>
--FILE--
<?php

try {
pcntl_setpriority(0, null, (PRIO_PGRP + PRIO_USER + PRIO_PROCESS + 10));
} catch (ValueError $exception) {
echo $exception->getMessage() . "\n";
}

try {
pcntl_setpriority(0, -1, PRIO_DARWIN_THREAD);
} catch (ValueError $exception) {
echo $exception->getMessage() . "\n";
}

try {
pcntl_setpriority(0, -123);
} catch (ValueError $exception) {
echo $exception->getMessage() . "\n";
}

pcntl_setpriority(-1000, 1);

?>
--EXPECTF--
pcntl_setpriority(): Argument #3 ($mode) must be one of PRIO_PGRP, PRIO_USER, PRIO_PROCESS or PRIO_DARWIN_THREAD
pcntl_setpriority(): Argument #2 ($process_id) must be 0 (zero) if PRIO_DARWIN_THREAD is provided as second parameter
pcntl_setpriority(): Argument #2 ($process_id) is not a valid process, process group, or user ID

Warning: pcntl_setpriority(): Error 1: A process was located, but neither its effective nor real user ID matched the effective user ID of the caller in %s
27 changes: 27 additions & 0 deletions ext/pcntl/tests/pcntl_setpriority_error_linux.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
--TEST--
pcntl_setpriority() - Check for errors
--EXTENSIONS--
pcntl
--SKIPIF--
<?php

if (!function_exists('pcntl_setpriority')) {
die('skip pcntl_setpriority doesn\'t exist');
}

if (PHP_OS !== "Linux") {
die("skip This test only runs on Linux");
}

?>
--FILE--
<?php

pcntl_setpriority(-1000, 1);
pcntl_setpriority(-1000, 0);

?>
--EXPECTF--
Warning: pcntl_setpriority(): Error 1: A process was located, but neither its effective nor real user ID matched the effective user ID of the caller in %s

Warning: pcntl_setpriority(): Error 13: Only a super user may attempt to increase the process priority in %s on line %d