From 5f7e7badae992d4df2aa28bc09bb856294faf975 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 5 Apr 2024 21:37:59 +0100 Subject: [PATCH 1/3] ext/pcntl: cpu affinity api introduction. For now, working on Linux, FreeBSD >= 13.x and DragonFlyBSD. Handy wrapper to assign an array of cpu ids or to retrieve the cpu ids assigned to a given process. pcntl_setaffinity inserts valid unique cpu ids (within the range of available cpus). --- ext/pcntl/config.m4 | 13 +++- ext/pcntl/pcntl.c | 104 ++++++++++++++++++++++++- ext/pcntl/pcntl.stub.php | 5 ++ ext/pcntl/pcntl_arginfo.h | 27 ++++++- ext/pcntl/tests/pcntl_cpuaffinity.phpt | 58 ++++++++++++++ 5 files changed, 204 insertions(+), 3 deletions(-) create mode 100644 ext/pcntl/tests/pcntl_cpuaffinity.phpt diff --git a/ext/pcntl/config.m4 b/ext/pcntl/config.m4 index 7e7a389615a8..4226fb1713ac 100644 --- a/ext/pcntl/config.m4 +++ b/ext/pcntl/config.m4 @@ -7,7 +7,18 @@ if test "$PHP_PCNTL" != "no"; then AC_CHECK_FUNCS([fork], [], [AC_MSG_ERROR([pcntl: fork() not supported by this platform])]) AC_CHECK_FUNCS([waitpid], [], [AC_MSG_ERROR([pcntl: waitpid() not supported by this platform])]) AC_CHECK_FUNCS([sigaction], [], [AC_MSG_ERROR([pcntl: sigaction() not supported by this platform])]) - AC_CHECK_FUNCS([getpriority setpriority wait3 wait4 sigwaitinfo sigtimedwait unshare rfork forkx pidfd_open]) + AC_CHECK_FUNCS([ + getpriority + setpriority + wait3 + wait4 + sigwaitinfo + sigtimedwait + unshare + rfork + forkx + pidfd_open + sched_setaffinity]) AC_CHECK_TYPE([siginfo_t],[PCNTL_CFLAGS="-DHAVE_STRUCT_SIGINFO_T"],,[#include ]) diff --git a/ext/pcntl/pcntl.c b/ext/pcntl/pcntl.c index 4c4d01c27ce5..6cb8c5775239 100644 --- a/ext/pcntl/pcntl.c +++ b/ext/pcntl/pcntl.c @@ -42,8 +42,13 @@ #endif #include -#ifdef HAVE_UNSHARE +#if defined(HAVE_UNSHARE) || defined(HAVE_SCHED_SETAFFINITY) #include +#if defined(__FreeBSD__) +#include +#include +typedef cpuset_t cpu_set_t; +#endif #endif #ifdef HAVE_PIDFD_OPEN @@ -1476,6 +1481,103 @@ PHP_FUNCTION(pcntl_setns) } #endif +#ifdef HAVE_SCHED_SETAFFINITY +PHP_FUNCTION(pcntl_getcpuaffinity) +{ + zend_long pid; + bool pid_is_null = 1; + cpu_set_t mask; + zend_ulong i, maxcpus; + + ZEND_PARSE_PARAMETERS_START(0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_LONG_OR_NULL(pid, pid_is_null) + ZEND_PARSE_PARAMETERS_END(); + + // 0 == getpid in this context, we re just saving a syscall + pid = pid_is_null ? 0 : pid; + + CPU_ZERO(&mask); + + if (sched_getaffinity(pid, sizeof(mask), &mask) != 0) { + PCNTL_G(last_error) = errno; + switch (errno) { + case ESRCH: + zend_argument_value_error(1, "invalid process (" ZEND_LONG_FMT ")", pid); + RETURN_THROWS(); + case EPERM: + php_error_docref(NULL, E_WARNING, "Calling process not having the proper privileges"); + break; + default: + php_error_docref(NULL, E_WARNING, "Error %d", errno); + } + + RETURN_EMPTY_ARRAY(); + } + + maxcpus = (zend_ulong)sysconf(_SC_NPROCESSORS_ONLN); + array_init(return_value); + + for (i = 0; i < maxcpus; i ++) { + if (CPU_ISSET(i, &mask)) { + add_next_index_long(return_value, i); + } + } +} + +PHP_FUNCTION(pcntl_setcpuaffinity) +{ + zend_long pid; + bool pid_is_null = 1; + cpu_set_t mask; + zval *hmask = NULL, *cpu; + zend_ulong maxcpus; + + ZEND_PARSE_PARAMETERS_START(0, 2) + Z_PARAM_OPTIONAL + Z_PARAM_LONG_OR_NULL(pid, pid_is_null) + Z_PARAM_ARRAY(hmask) + ZEND_PARSE_PARAMETERS_END(); + + if (!hmask || Z_ARRVAL_P(hmask)->nNumOfElements == 0) { + zend_argument_value_error(2, "must not be empty"); + RETURN_THROWS(); + } + + // 0 == getpid in this context, we re just saving a syscall + pid = pid_is_null ? 0 : pid; + maxcpus = sysconf(_SC_NPROCESSORS_ONLN); + CPU_ZERO(&mask); + + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(hmask), cpu) { + if (Z_TYPE_P(cpu) == IS_LONG && Z_LVAL_P(cpu) >= 0 && + Z_LVAL_P(cpu) < maxcpus && !CPU_ISSET(Z_LVAL_P(cpu), &mask)) { + CPU_SET(Z_LVAL_P(cpu), &mask); + } + } ZEND_HASH_FOREACH_END(); + + if (!CPU_COUNT(&mask)) { + zend_argument_value_error(2, "invalid cpu affinity mapping"); + RETURN_THROWS(); + } + + if (sched_setaffinity(pid, sizeof(mask), &mask) != 0) { + PCNTL_G(last_error) = errno; + switch (errno) { + case ESRCH: + zend_argument_value_error(1, "invalid process (" ZEND_LONG_FMT ")", pid); + RETURN_THROWS(); + case EPERM: + php_error_docref(NULL, E_WARNING, "Calling process not having the proper privileges"); + break; + } + RETURN_FALSE; + } else { + RETURN_TRUE; + } +} +#endif + static void pcntl_interrupt_function(zend_execute_data *execute_data) { pcntl_signal_dispatch(); diff --git a/ext/pcntl/pcntl.stub.php b/ext/pcntl/pcntl.stub.php index a2420f335236..cbee0829799d 100644 --- a/ext/pcntl/pcntl.stub.php +++ b/ext/pcntl/pcntl.stub.php @@ -994,3 +994,8 @@ function pcntl_forkx(int $flags): int{} #ifdef HAVE_PIDFD_OPEN function pcntl_setns(?int $process_id = null, int $nstype = CLONE_NEWNET): bool {} #endif + +#ifdef HAVE_SCHED_SETAFFINITY +function pcntl_getcpuaffinity(?int $process_id = null): array {} +function pcntl_setcpuaffinity(?int $process_id = null, array $cpu_ids = []): bool {} +#endif diff --git a/ext/pcntl/pcntl_arginfo.h b/ext/pcntl/pcntl_arginfo.h index cd16e4f19cd6..490a013aa0bd 100644 --- a/ext/pcntl/pcntl_arginfo.h +++ b/ext/pcntl/pcntl_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: e5204cee68c41ff1201992f2572940c8f87980a3 */ + * Stub hash: 3b3fd6aaaca61451cad2679aafa3abef1a7056db */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pcntl_fork, 0, 0, IS_LONG, 0) ZEND_END_ARG_INFO() @@ -139,6 +139,19 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pcntl_setns, 0, 0, _IS_BOOL, 0) ZEND_END_ARG_INFO() #endif +#if defined(HAVE_SCHED_SETAFFINITY) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pcntl_getcpuaffinity, 0, 0, IS_ARRAY, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, process_id, IS_LONG, 1, "null") +ZEND_END_ARG_INFO() +#endif + +#if defined(HAVE_SCHED_SETAFFINITY) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pcntl_setcpuaffinity, 0, 0, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, process_id, IS_LONG, 1, "null") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cpu_ids, IS_ARRAY, 0, "[]") +ZEND_END_ARG_INFO() +#endif + ZEND_FUNCTION(pcntl_fork); ZEND_FUNCTION(pcntl_waitpid); ZEND_FUNCTION(pcntl_wait); @@ -186,6 +199,12 @@ ZEND_FUNCTION(pcntl_forkx); #if defined(HAVE_PIDFD_OPEN) ZEND_FUNCTION(pcntl_setns); #endif +#if defined(HAVE_SCHED_SETAFFINITY) +ZEND_FUNCTION(pcntl_getcpuaffinity); +#endif +#if defined(HAVE_SCHED_SETAFFINITY) +ZEND_FUNCTION(pcntl_setcpuaffinity); +#endif static const zend_function_entry ext_functions[] = { ZEND_FE(pcntl_fork, arginfo_pcntl_fork) @@ -235,6 +254,12 @@ static const zend_function_entry ext_functions[] = { #endif #if defined(HAVE_PIDFD_OPEN) ZEND_FE(pcntl_setns, arginfo_pcntl_setns) +#endif +#if defined(HAVE_SCHED_SETAFFINITY) + ZEND_FE(pcntl_getcpuaffinity, arginfo_pcntl_getcpuaffinity) +#endif +#if defined(HAVE_SCHED_SETAFFINITY) + ZEND_FE(pcntl_setcpuaffinity, arginfo_pcntl_setcpuaffinity) #endif ZEND_FE_END }; diff --git a/ext/pcntl/tests/pcntl_cpuaffinity.phpt b/ext/pcntl/tests/pcntl_cpuaffinity.phpt new file mode 100644 index 000000000000..8835b6cc0fed --- /dev/null +++ b/ext/pcntl/tests/pcntl_cpuaffinity.phpt @@ -0,0 +1,58 @@ +--TEST-- +pcntl_getcpuaffinity() and pcntl_setcpuaffinity() +--EXTENSIONS-- +pcntl +--SKIPIF-- + +--FILE-- +getMessage() . PHP_EOL; +} + +try { + pcntl_setcpuaffinity(null, ["abc" => "def", 0 => "cpuid"]); +} catch (\ValueError $e) { + echo $e->getMessage() . PHP_EOL; +} + +try { + pcntl_setcpuaffinity(null, [PHP_INT_MAX]); +} catch (\ValueError $e) { + echo $e->getMessage() . PHP_EOL; +} + +try { + pcntl_setcpuaffinity(null, [-1024, 64, -2]); +} catch (\ValueError $e) { + echo $e->getMessage() . PHP_EOL; +} + +try { + pcntl_getcpuaffinity(-1024); +} catch (\ValueError $e) { + echo $e->getMessage(); +} +?> +--EXPECT-- +bool(true) +array(0) { +} +array(0) { +} +pcntl_setcpuaffinity(): Argument #2 ($cpu_ids) must not be empty +pcntl_setcpuaffinity(): Argument #2 ($cpu_ids) invalid cpu affinity mapping +pcntl_setcpuaffinity(): Argument #2 ($cpu_ids) invalid cpu affinity mapping +pcntl_setcpuaffinity(): Argument #2 ($cpu_ids) invalid cpu affinity mapping +pcntl_getcpuaffinity(): Argument #1 ($process_id) invalid process (-1024) From d1bce658b820bd2d71dd9b89d32a81f0f9ff0215 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 6 Apr 2024 14:46:08 +0100 Subject: [PATCH 2/3] changes from feedback --- ext/pcntl/pcntl.c | 51 ++++++++++++++++---------- ext/pcntl/pcntl.stub.php | 2 +- ext/pcntl/pcntl_arginfo.h | 4 +- ext/pcntl/tests/pcntl_cpuaffinity.phpt | 18 +++++++-- 4 files changed, 49 insertions(+), 26 deletions(-) diff --git a/ext/pcntl/pcntl.c b/ext/pcntl/pcntl.c index 6cb8c5775239..d262ee96e505 100644 --- a/ext/pcntl/pcntl.c +++ b/ext/pcntl/pcntl.c @@ -1487,14 +1487,13 @@ PHP_FUNCTION(pcntl_getcpuaffinity) zend_long pid; bool pid_is_null = 1; cpu_set_t mask; - zend_ulong i, maxcpus; ZEND_PARSE_PARAMETERS_START(0, 1) Z_PARAM_OPTIONAL Z_PARAM_LONG_OR_NULL(pid, pid_is_null) ZEND_PARSE_PARAMETERS_END(); - // 0 == getpid in this context, we re just saving a syscall + // 0 == getpid in this context, we're just saving a syscall pid = pid_is_null ? 0 : pid; CPU_ZERO(&mask); @@ -1512,13 +1511,13 @@ PHP_FUNCTION(pcntl_getcpuaffinity) php_error_docref(NULL, E_WARNING, "Error %d", errno); } - RETURN_EMPTY_ARRAY(); + RETURN_FALSE; } - maxcpus = (zend_ulong)sysconf(_SC_NPROCESSORS_ONLN); + zend_ulong maxcpus = (zend_ulong)sysconf(_SC_NPROCESSORS_ONLN); array_init(return_value); - for (i = 0; i < maxcpus; i ++) { + for (zend_ulong i = 0; i < maxcpus; i ++) { if (CPU_ISSET(i, &mask)) { add_next_index_long(return_value, i); } @@ -1530,8 +1529,7 @@ PHP_FUNCTION(pcntl_setcpuaffinity) zend_long pid; bool pid_is_null = 1; cpu_set_t mask; - zval *hmask = NULL, *cpu; - zend_ulong maxcpus; + zval *hmask = NULL, *ncpu; ZEND_PARSE_PARAMETERS_START(0, 2) Z_PARAM_OPTIONAL @@ -1539,27 +1537,40 @@ PHP_FUNCTION(pcntl_setcpuaffinity) Z_PARAM_ARRAY(hmask) ZEND_PARSE_PARAMETERS_END(); - if (!hmask || Z_ARRVAL_P(hmask)->nNumOfElements == 0) { + if (!hmask || zend_hash_num_elements(Z_ARRVAL_P(hmask)) == 0) { zend_argument_value_error(2, "must not be empty"); RETURN_THROWS(); } - // 0 == getpid in this context, we re just saving a syscall + // 0 == getpid in this context, we're just saving a syscall pid = pid_is_null ? 0 : pid; - maxcpus = sysconf(_SC_NPROCESSORS_ONLN); + zend_ulong maxcpus = (zend_ulong)sysconf(_SC_NPROCESSORS_ONLN); CPU_ZERO(&mask); - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(hmask), cpu) { - if (Z_TYPE_P(cpu) == IS_LONG && Z_LVAL_P(cpu) >= 0 && - Z_LVAL_P(cpu) < maxcpus && !CPU_ISSET(Z_LVAL_P(cpu), &mask)) { - CPU_SET(Z_LVAL_P(cpu), &mask); + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(hmask), ncpu) { + ZVAL_DEREF(ncpu); + zend_long cpu; + if (Z_TYPE_P(ncpu) != IS_LONG) { + if (Z_TYPE_P(ncpu) == IS_STRING) { + cpu = zval_get_long(ncpu); + } else { + zend_string *wcpu = zval_get_string_func(ncpu); + zend_value_error("cpu id invalid type (%s)", ZSTR_VAL(wcpu)); + RETURN_THROWS(); + } + } else { + cpu = Z_LVAL_P(ncpu); } - } ZEND_HASH_FOREACH_END(); - if (!CPU_COUNT(&mask)) { - zend_argument_value_error(2, "invalid cpu affinity mapping"); - RETURN_THROWS(); - } + if (cpu < 0 || cpu >= maxcpus) { + zend_value_error("cpu id must be between 0 and " ZEND_ULONG_FMT " (" ZEND_LONG_FMT ")", maxcpus, cpu); + RETURN_THROWS(); + } + + if (!CPU_ISSET(cpu, &mask)) { + CPU_SET(cpu, &mask); + } + } ZEND_HASH_FOREACH_END(); if (sched_setaffinity(pid, sizeof(mask), &mask) != 0) { PCNTL_G(last_error) = errno; @@ -1570,6 +1581,8 @@ PHP_FUNCTION(pcntl_setcpuaffinity) case EPERM: php_error_docref(NULL, E_WARNING, "Calling process not having the proper privileges"); break; + default: + php_error_docref(NULL, E_WARNING, "Error %d", errno); } RETURN_FALSE; } else { diff --git a/ext/pcntl/pcntl.stub.php b/ext/pcntl/pcntl.stub.php index cbee0829799d..da90057e437d 100644 --- a/ext/pcntl/pcntl.stub.php +++ b/ext/pcntl/pcntl.stub.php @@ -996,6 +996,6 @@ function pcntl_setns(?int $process_id = null, int $nstype = CLONE_NEWNET): bool #endif #ifdef HAVE_SCHED_SETAFFINITY -function pcntl_getcpuaffinity(?int $process_id = null): array {} +function pcntl_getcpuaffinity(?int $process_id = null): array|false {} function pcntl_setcpuaffinity(?int $process_id = null, array $cpu_ids = []): bool {} #endif diff --git a/ext/pcntl/pcntl_arginfo.h b/ext/pcntl/pcntl_arginfo.h index 490a013aa0bd..b9ac54657abb 100644 --- a/ext/pcntl/pcntl_arginfo.h +++ b/ext/pcntl/pcntl_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 3b3fd6aaaca61451cad2679aafa3abef1a7056db */ + * Stub hash: a61b0327f5c36ca91e19c5f370377794b7950dee */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pcntl_fork, 0, 0, IS_LONG, 0) ZEND_END_ARG_INFO() @@ -140,7 +140,7 @@ ZEND_END_ARG_INFO() #endif #if defined(HAVE_SCHED_SETAFFINITY) -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pcntl_getcpuaffinity, 0, 0, IS_ARRAY, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_pcntl_getcpuaffinity, 0, 0, MAY_BE_ARRAY|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, process_id, IS_LONG, 1, "null") ZEND_END_ARG_INFO() #endif diff --git a/ext/pcntl/tests/pcntl_cpuaffinity.phpt b/ext/pcntl/tests/pcntl_cpuaffinity.phpt index 8835b6cc0fed..365cccea1202 100644 --- a/ext/pcntl/tests/pcntl_cpuaffinity.phpt +++ b/ext/pcntl/tests/pcntl_cpuaffinity.phpt @@ -14,6 +14,7 @@ $act_mask = pcntl_getcpuaffinity(); var_dump(array_diff($mask, $act_mask)); $n_act_mask = pcntl_getcpuaffinity(); var_dump(array_diff($act_mask, $n_act_mask)); +var_dump(pcntl_setcpuaffinity(null, ["0", "1"])); try { pcntl_setcpuaffinity(null, []); @@ -41,18 +42,27 @@ try { try { pcntl_getcpuaffinity(-1024); +} catch (\ValueError $e) { + echo $e->getMessage() . PHP_EOL; +} + +try { + pcntl_setcpuaffinity(null, [1, array(1)]); } catch (\ValueError $e) { echo $e->getMessage(); } ?> ---EXPECT-- +--EXPECTF-- bool(true) array(0) { } array(0) { } +bool(true) pcntl_setcpuaffinity(): Argument #2 ($cpu_ids) must not be empty -pcntl_setcpuaffinity(): Argument #2 ($cpu_ids) invalid cpu affinity mapping -pcntl_setcpuaffinity(): Argument #2 ($cpu_ids) invalid cpu affinity mapping -pcntl_setcpuaffinity(): Argument #2 ($cpu_ids) invalid cpu affinity mapping +cpu id must be between 0 and %d (%d) +cpu id must be between 0 and %d (-1024) pcntl_getcpuaffinity(): Argument #1 ($process_id) invalid process (-1024) + +Warning: Array to string conversion in %s on line %d +cpu id invalid type (Array) From 866fbc28b9ef50568b272f2044222acf36fa06f7 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 6 Apr 2024 23:46:47 +0100 Subject: [PATCH 3/3] using _SC_NPROCESSORS_CONF instead in case of cpu put offline. addressing other remarks. --- ext/pcntl/config.m4 | 13 +------------ ext/pcntl/pcntl.c | 17 ++++++++++++----- ext/pcntl/tests/pcntl_cpuaffinity.phpt | 7 ++++--- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/ext/pcntl/config.m4 b/ext/pcntl/config.m4 index 4226fb1713ac..89475c44e6f8 100644 --- a/ext/pcntl/config.m4 +++ b/ext/pcntl/config.m4 @@ -7,18 +7,7 @@ if test "$PHP_PCNTL" != "no"; then AC_CHECK_FUNCS([fork], [], [AC_MSG_ERROR([pcntl: fork() not supported by this platform])]) AC_CHECK_FUNCS([waitpid], [], [AC_MSG_ERROR([pcntl: waitpid() not supported by this platform])]) AC_CHECK_FUNCS([sigaction], [], [AC_MSG_ERROR([pcntl: sigaction() not supported by this platform])]) - AC_CHECK_FUNCS([ - getpriority - setpriority - wait3 - wait4 - sigwaitinfo - sigtimedwait - unshare - rfork - forkx - pidfd_open - sched_setaffinity]) + AC_CHECK_FUNCS([getpriority setpriority wait3 wait4 sigwaitinfo sigtimedwait unshare rfork forkx pidfd_open sched_setaffinity]) AC_CHECK_TYPE([siginfo_t],[PCNTL_CFLAGS="-DHAVE_STRUCT_SIGINFO_T"],,[#include ]) diff --git a/ext/pcntl/pcntl.c b/ext/pcntl/pcntl.c index d262ee96e505..fcd2315e8c24 100644 --- a/ext/pcntl/pcntl.c +++ b/ext/pcntl/pcntl.c @@ -1514,7 +1514,7 @@ PHP_FUNCTION(pcntl_getcpuaffinity) RETURN_FALSE; } - zend_ulong maxcpus = (zend_ulong)sysconf(_SC_NPROCESSORS_ONLN); + zend_ulong maxcpus = (zend_ulong)sysconf(_SC_NPROCESSORS_CONF); array_init(return_value); for (zend_ulong i = 0; i < maxcpus; i ++) { @@ -1544,7 +1544,7 @@ PHP_FUNCTION(pcntl_setcpuaffinity) // 0 == getpid in this context, we're just saving a syscall pid = pid_is_null ? 0 : pid; - zend_ulong maxcpus = (zend_ulong)sysconf(_SC_NPROCESSORS_ONLN); + zend_ulong maxcpus = (zend_ulong)sysconf(_SC_NPROCESSORS_CONF); CPU_ZERO(&mask); ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(hmask), ncpu) { @@ -1552,10 +1552,17 @@ PHP_FUNCTION(pcntl_setcpuaffinity) zend_long cpu; if (Z_TYPE_P(ncpu) != IS_LONG) { if (Z_TYPE_P(ncpu) == IS_STRING) { - cpu = zval_get_long(ncpu); + zend_ulong tmp; + if (!ZEND_HANDLE_NUMERIC(Z_STR_P(ncpu), tmp)) { + zend_argument_value_error(2, "cpu id invalid value (%s)", ZSTR_VAL(Z_STR_P(ncpu))); + RETURN_THROWS(); + } + + cpu = (zend_long)tmp; } else { zend_string *wcpu = zval_get_string_func(ncpu); - zend_value_error("cpu id invalid type (%s)", ZSTR_VAL(wcpu)); + zend_argument_value_error(2, "cpu id invalid type (%s)", ZSTR_VAL(wcpu)); + zend_string_release(wcpu); RETURN_THROWS(); } } else { @@ -1563,7 +1570,7 @@ PHP_FUNCTION(pcntl_setcpuaffinity) } if (cpu < 0 || cpu >= maxcpus) { - zend_value_error("cpu id must be between 0 and " ZEND_ULONG_FMT " (" ZEND_LONG_FMT ")", maxcpus, cpu); + zend_argument_value_error(2, "cpu id must be between 0 and " ZEND_ULONG_FMT " (" ZEND_LONG_FMT ")", maxcpus, cpu); RETURN_THROWS(); } diff --git a/ext/pcntl/tests/pcntl_cpuaffinity.phpt b/ext/pcntl/tests/pcntl_cpuaffinity.phpt index 365cccea1202..6dc3399e1611 100644 --- a/ext/pcntl/tests/pcntl_cpuaffinity.phpt +++ b/ext/pcntl/tests/pcntl_cpuaffinity.phpt @@ -60,9 +60,10 @@ array(0) { } bool(true) pcntl_setcpuaffinity(): Argument #2 ($cpu_ids) must not be empty -cpu id must be between 0 and %d (%d) -cpu id must be between 0 and %d (-1024) +pcntl_setcpuaffinity(): Argument #2 ($cpu_ids) cpu id invalid value (def) +pcntl_setcpuaffinity(): Argument #2 ($cpu_ids) cpu id must be between 0 and %d (%d) +pcntl_setcpuaffinity(): Argument #2 ($cpu_ids) cpu id must be between 0 and %d (-1024) pcntl_getcpuaffinity(): Argument #1 ($process_id) invalid process (-1024) Warning: Array to string conversion in %s on line %d -cpu id invalid type (Array) +pcntl_setcpuaffinity(): Argument #2 ($cpu_ids) cpu id invalid type (Array)