The 'nice' program should execute the given program even if the adjusted
niceness is too large. On GNU/Linux, for example, it is correctly
adjusted to the maximum niceness:
$ /bin/nice -n +1000 /bin/nice
19
On GNU/Hurd this does not occur, and a confusing error message is
printed instead:
$ /bin/nice -n +100 /bin/nice
nice: cannot set niceness: No such process
This is because on GNU/Hurd the supported niceness ranges from 0 to 38
instead of -20 to 19 like on most other systems. This can be seen using
the following test program:
$ cat main.c
#define _GNU_SOURCE 1
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
int
main (void)
{
errno = 0;
int starting_nice = nice (0);
if (starting_nice == -1 && errno != 0)
{
fprintf (stderr, "starting nice failed: %s\n",
strerror (errno));
return EXIT_FAILURE;
}
int minimum_nice = starting_nice;
for (;;)
{
errno = 0;
int result = nice (-1);
if (result == -1 && errno != 0)
break;
minimum_nice = result;
}
int minimum_errno = errno;
int maximum_nice = minimum_nice;
for (;;)
{
errno = 0;
int result = nice (1);
if (result == -1 && errno != 0)
break;
maximum_nice = result;
}
int maximum_errno = errno;
printf ("starting nice: %d\n", starting_nice);
printf ("minimum nice: %d\n", minimum_nice);
printf ("maximum nice: %d\n", maximum_nice);
printf ("minimum errno: %s\n", strerrorname_np (minimum_errno));
printf ("maximum errno: %s\n", strerrorname_np (maximum_errno));
return EXIT_FAILURE;
}
That test program assumes that nice() does not clamp the niceness to the
supported range as it is supposed to [1]. This is the case on GNU/Hurd,
so I will submit a bug report for that later.
The output is the same on a normal and privileged user:
$ gcc main.c ./a.out
starting nice: 0
minimum nice: 0
maximum nice: 38
minimum errno: EPERM
maximum errno: ESRCH
This patch clamps it to the supported range and adds some tests. Here is
the corrected behavior:
$ ./src/nice -n +100 ./src/nice
38
Collin
[1] https://pubs.opengroup.org/onlinepubs/9799919799/functions/nice.html
>From ee66dca4af75493687d3fc831d2cd0dea9451728 Mon Sep 17 00:00:00 2001
Message-ID: <ee66dca4af75493687d3fc831d2cd0dea9451728.1762665726.git.collin.fu...@gmail.com>
From: Collin Funk <[email protected]>
Date: Sat, 8 Nov 2025 20:30:08 -0800
Subject: [PATCH] nice: clamp the niceness correctly on GNU/Hurd
* NEWS: Mention the bug fix.
* src/nice.c (MIN_ADJUSTMENT): Set to 0 on the Hurd.
(MAX_ADJUSTMENT): Set to 38 on the Hurd.
* tests/nice/nice.sh: Add some tests for the Hurd's ranges.
---
NEWS | 4 ++++
src/nice.c | 5 +++++
tests/nice/nice.sh | 32 ++++++++++++++++++++++----------
3 files changed, 31 insertions(+), 10 deletions(-)
diff --git a/NEWS b/NEWS
index 7e7dc6376..46df91b62 100644
--- a/NEWS
+++ b/NEWS
@@ -26,6 +26,10 @@ GNU coreutils NEWS -*- outline -*-
will no longer always set a __CF_USER_TEXT_ENCODING environment variable.
[bug introduced in coreutils-9.8]
+ 'nice' now limits the adjusted niceness value to its supported range on
+ GNU/Hurd.
+ [This bug was present in "the beginning".]
+
'numfmt' no longer reads out-of-bounds memory with trailing blanks in input.
[bug introduced with numfmt in coreutils-8.21]
diff --git a/src/nice.c b/src/nice.c
index 1c3f2a038..a7cdbbdc2 100644
--- a/src/nice.c
+++ b/src/nice.c
@@ -167,7 +167,12 @@ main (int argc, char **argv)
/* If the requested adjustment is outside the valid range,
silently bring it to just within range; this mimics what
"setpriority" and "nice" do. */
+#ifdef __gnu_hurd__
+ /* GNU/Hurd's range is 0 to 38. */
+ enum { MIN_ADJUSTMENT = 0, MAX_ADJUSTMENT = 38 };
+#else
enum { MIN_ADJUSTMENT = 1 - 2 * NZERO, MAX_ADJUSTMENT = 2 * NZERO - 1 };
+#endif
long int tmp;
if (LONGINT_OVERFLOW < xstrtol (adjustment_given, nullptr, 10, &tmp, ""))
error (EXIT_CANCELED, 0, _("invalid adjustment %s"),
diff --git a/tests/nice/nice.sh b/tests/nice/nice.sh
index 7e274ca0d..9c42e3054 100755
--- a/tests/nice/nice.sh
+++ b/tests/nice/nice.sh
@@ -71,16 +71,28 @@ done
# Test negative niceness - command must be run whether or not change happens.
if test x$(nice -n -1 nice 2> /dev/null) = x0 ; then
- # unprivileged user - warn about failure to change
- nice -n -1 true 2> err || fail=1
- compare /dev/null err && fail=1
- mv err exp || framework_failure_
- nice --1 true 2> err || fail=1
- compare exp err || fail=1
- # Failure to write advisory message is fatal. Buggy through coreutils 8.0.
- if test -w /dev/full && test -c /dev/full; then
- returns_ 125 nice -n -1 nice > out 2> /dev/full || fail=1
- compare /dev/null out || fail=1
+ # GNU/Hurd does not allow negative niceness even if we are privileged user.
+ if test "$(uname)" = GNU; then
+ # Check that the lowest niceness is 0.
+ nice -n -1 nice > out || fail=1
+ echo '0' > exp || framework_failure_
+ compare exp out || fail=1
+ # Check that the highest niceness is 38.
+ nice -n 39 nice > out || fail=1
+ echo '38' > exp || framework_failure_
+ compare exp out || fail=1
+ else
+ # unprivileged user - warn about failure to change
+ nice -n -1 true 2> err || fail=1
+ compare /dev/null err && fail=1
+ mv err exp || framework_failure_
+ nice --1 true 2> err || fail=1
+ compare exp err || fail=1
+ # Failure to write advisory message is fatal. Buggy through coreutils 8.0.
+ if test "$(uname)" != GNU && test -w /dev/full && test -c /dev/full; then
+ returns_ 125 nice -n -1 nice > out 2> /dev/full || fail=1
+ compare /dev/null out || fail=1
+ fi
fi
else
# superuser - change succeeds
--
2.51.1