The core implementation details are described in win32/nice.c for values sent to proc_nice(), these can however be discussed to maybe comply with those of wmic, Anatol, thoughts?
The test supplied uses wmic for testing the functionality, it could potentially fail on systems where either wmic is not available or the system language is not english (as Microsoft tends to translate even CLI programs).
- Core:
. Removed the sql.safe_mode directive. (Kalle)
. Fixed bug #54535 (WSA cleanup executes before MSHUTDOWN). (Kalle)
- . Implemented bug #69791 (Disallow mail header injections by extra headers)
+ . Implemented FR #69791 (Disallow mail header injections by extra headers)
(Yasuo)
+ . Implemented FR #49806 (proc_nice() for Windows). (Kalle)
- EXIF:
. Added support for vendor specific tags for the following formats:
- Standard:
. Simplified password hashing API updated to support Argon2i hashes when PHP is compiled with libargon2
(https://wiki.php.net/rfc/argon2_password_hash).
+ . proc_nice() is now supported on Windows platforms.
========================================
3. Changes in SAPI modules
b. Windows build system changes
+ * nice() now have a Windows alternative that is implemented in win32/nice.c, using
+ SetPriorityClass(). See the implementation for more in-depth details. This also
+ defines HAVE_NICE.
+
========================
3. Module changes
========================
errno = 0;
php_ignore_value(nice(pri));
if (errno) {
+#ifdef PHP_WIN32
+ php_error_docref(NULL, E_WARNING, php_win_err());
+#else
php_error_docref(NULL, E_WARNING, "Only a super user may attempt to increase the priority of a process");
+#endif
RETURN_FALSE;
}
--- /dev/null
+--TEST--
+proc_nice() basic behaviour
+--SKIPIF--
+<?php
+/* No function_exists() check, proc_nice() is always available on Windows */
+
+if (!defined('PHP_WINDOWS_VERSION_MAJOR')) {
+ die('skip: Only for Windows');
+}
+
+if (PHP_SAPI != 'cli') {
+ die('skip: Only for CLI');
+}
+
+if (getenv('SKIP_SLOW_TESTS')) {
+ doe('skip: Slow test');
+}
+?>
+--FILE--
+<?php
+function get_priority_from_wmic() {
+ static $bin, $pid;
+
+ if (!$bin) {
+ $t = explode('\\', PHP_BINARY);
+
+ $bin = end($t);
+ $pid = getmypid();
+ }
+
+ $t = '';
+ $p = popen('wmic process where name="' . $bin . '"', 'r');
+
+ if (!$p) {
+ return false;
+ }
+
+ while(!feof($p)) {
+ $t .= fread($p, 1024);
+ }
+
+ pclose($p);
+
+ $t = explode(PHP_EOL, $t);
+
+ $f = false;
+ $m = [
+ strpos($t[0], ' ProcessId' ),
+ strpos($t[0], ' Priority ')
+ ];
+
+ foreach ($t as $n => $l) {
+ if (!$n || empty($l)) {
+ continue;
+ }
+
+ $d = [];
+
+ foreach ($m as $c) {
+ $d[] = (int) substr($l, $c + 1, strpos($l, ' ', $c + 2) - ($c + 1));
+ }
+
+ if ($d[0] === $pid) {
+ return $d[1];
+ }
+ }
+
+ return false;
+}
+
+$p = [
+ /* '<verbose name>' => ['<wmic value>', '<proc_nice value>'] */
+
+ 'Idle' => [6, -10],
+ 'Below normal' => [4, -3],
+ 'Normal' => [8, 0],
+ 'Above normal' => [10, 4],
+ 'High priority' => [13, 5],
+ 'Real time' => [24, 8]
+ ];
+
+foreach ($p as $test => $data) {
+ printf('Testing \'%s\' (%d): ', $test, $data[1]);
+
+ proc_nice($data[1]);
+
+ print (get_priority_from_wmic() === $data[0] ? 'Passed' : 'Failed') . PHP_EOL;
+}
+?>
+--EXPECTF--
+Testing 'Idle' (-10): Passed
+Testing 'Below normal' (-3): Passed
+Testing 'Normal' (0): Passed
+Testing 'Above normal' (4): Passed
+Testing 'High priority' (5): Passed
+Testing 'Real time' (8): Passed
--SKIPIF--
<?php
if(!function_exists('proc_nice')) die("skip. proc_nice not available ");
+if(substr(strtoupper(PHP_OS), 0, 3) == 'WIN') die('skip. not for Windows');
?>
--FILE--
<?php
ADD_SOURCES("win32", "dllmain.c glob.c readdir.c \
registry.c select.c sendmail.c time.c winutil.c wsyslog.c globals.c \
- getrusage.c ftok.c ioutil.c codepage.c");
+ getrusage.c ftok.c ioutil.c codepage.c nice.c");
ADD_FLAG("CFLAGS_BD_WIN32", "/D ZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
#define HAVE_GETRUSAGE
#define HAVE_FTOK 1
+
+#define HAVE_NICE
--- /dev/null
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 7 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2016 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | 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. |
+ +----------------------------------------------------------------------+
+ | Authors: Kalle Sommer Nielsen <kalle@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#include <php.h>
+#include "nice.h"
+
+/*
+ * Basic Windows implementation for the nice() function.
+ *
+ * This implementation uses SetPriorityClass() as a backend for defining
+ * a process priority.
+ *
+ * The following values of inc, defines the value sent to SetPriorityClass():
+ *
+ * +-----------------------+-----------------------------+
+ * | Expression | Priority type |
+ * +-----------------------+-----------------------------+
+ * | priority > 5 | REALTIME_PRIORITY_CLASS |
+ * +-----------------------+-----------------------------+
+ * | priority == 5 | HIGH_PRIORITY_CLASS |
+ * +-----------------------+-----------------------------+
+ * | priority > 0 | ABOVE_NORMAL_PRIORITY_CLASS |
+ * +-----------------------+-----------------------------+
+ * | priority == 0 | NORMAL_PRIORITY_CLASS |
+ * +-----------------------+-----------------------------+
+ * | priority < -5 | BELOW_NORMAL_PRIORITY_CLASS |
+ * +-----------------------+-----------------------------+
+ * | priority < -10 | IDLE_PRIORITY_CLASS |
+ * +-----------------------+-----------------------------+
+ *
+ * This is applied to the main process, not per thread, although this could
+ * be implemented using SetThreadPriority() at one point.
+ */
+
+PHPAPI int nice(zend_long p)
+{
+ DWORD dwFlag = NORMAL_PRIORITY_CLASS;
+
+ if (p > 5) {
+ dwFlag = REALTIME_PRIORITY_CLASS;
+ } else if (p == 5) {
+ dwFlag = HIGH_PRIORITY_CLASS;
+ } else if (p > 0) {
+ dwFlag = ABOVE_NORMAL_PRIORITY_CLASS;
+ } else if (p < 0 && p < -5) {
+ dwFlag = BELOW_NORMAL_PRIORITY_CLASS;
+ } else if (p < -10) {
+ dwFlag = IDLE_PRIORITY_CLASS;
+ }
+
+ if (!SetPriorityClass(GetCurrentProcess(), dwFlag)) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
--- /dev/null
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 7 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2016 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | 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. |
+ +----------------------------------------------------------------------+
+ | Authors: Kalle Sommer Nielsen <kalle@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifndef HAVE_GETRUSAGE_H
+# define HAVE_GETRUSAGE_H
+
+PHPAPI int nice(zend_long);
+
+#endif
+