bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

nice fixes for coreutils


From: Paul Eggert
Subject: nice fixes for coreutils
Date: Sun, 25 Jul 2004 23:17:03 -0700
User-agent: Gnus/5.1006 (Gnus v5.10.6) Emacs/21.3 (gnu/linux)

I installed the following patch to fix some POSIX and portability bugs
in the "nice" command.

2004-07-25  Paul Eggert  <address@hidden>

        * doc/coreutils.texi (nice invocation): Document the "nice value", and
        how it affects the scheduling priority.  (The old documentation
        implied that the nice value equaled the scheduling priority, which
        isn't accurate.)  Document that the range of nice values might
        exceed -20..19.  Specify what happens when you give a nice value
        that is out of range, or when you don't have permissions to lower
        the nice value.  Bash doesn't have a builtin 'nice', so don't say
        "most shells" have one.
        * src/nice.c (GET_NICE_VALUE): Renamed from GET_PRIORITY.
        All uses changed.
        (NZERO): New macro, if system doesn't define it already.
        (usage): Distinguish priorities from nice values.
        Don't assume NZERO is 20.
        (main): Use bool instead of int where appropriate.
        If user specifies an adjustment out of range, always truncate it
        to an inrange value instead of sometimes giving an error message
        and sometimes not.
        Do not assume that -1 is an error return from "nice" or
        "getpriority", as it might be the current nice value minus NZERO.
        If nice/setpriority fails with errno == EPERM, go ahead and run
        the command anyway; POSIX requires this.

Index: NEWS
===================================================================
RCS file: /home/eggert/coreutils/cu/NEWS,v
retrieving revision 1.225
diff -p -u -r1.225 NEWS
--- NEWS        23 Jul 2004 22:11:15 -0000      1.225
+++ NEWS        26 Jul 2004 06:05:35 -0000
@@ -48,6 +48,19 @@ GNU coreutils NEWS                      
   If d/x is a directory and x a file, "ln x d/" now reports an error
   instead of incorrectly creating a link to d/x/x.
 
+  Fixes for "nice":
+
+    If it fails to lower the nice value due to lack of permissions,
+    it goes ahead and runs the command anyway, as POSIX requires.
+
+    It no longer incorrectly reports an error if the current nice
+    value happens to be -1.
+
+    It no longer assumes that nice values range from -20 through 19.
+
+    It now consistently adjusts out-of-range nice values to the
+    closest values in range; formerly it sometimes reported an error.
+
   ptx now diagnoses invalid values for its --width=N (-w)
   and --gap-size=N (-g) options.
 
Index: doc/coreutils.texi
===================================================================
RCS file: /home/eggert/coreutils/cu/doc/coreutils.texi,v
retrieving revision 1.197
diff -p -u -r1.197 coreutils.texi
--- doc/coreutils.texi  23 Jul 2004 22:11:49 -0000      1.197
+++ doc/coreutils.texi  26 Jul 2004 06:00:32 -0000
@@ -11997,29 +11997,35 @@ the exit status of @var{command} otherwi
 @section @command{nice}: Run a command with modified scheduling priority
 
 @pindex nice
address@hidden nice value
 @cindex modifying scheduling priority
 @cindex scheduling priority, modifying
 @cindex priority, modifying
 @cindex appropriate privileges
 
address@hidden prints or modifies the scheduling priority of a job.
address@hidden prints or modifies a process's @dfn{nice value},
+a parameter that affects the process's scheduling priority.
 Synopsis:
 
 @example
 nice address@hidden@dots{} address@hidden address@hidden@dots{}]
 @end example
 
-If no arguments are given, @command{nice} prints the current scheduling
-priority, which it inherited.  Otherwise, @command{nice} runs the given
address@hidden with its scheduling priority adjusted.  If no
address@hidden is given, the priority of the command is incremented by
-10.  You must have appropriate privileges to specify a negative
-adjustment.  The priority can be adjusted by @command{nice} over the range
-of @minus{}20 (the highest priority) to 19 (the lowest).
+If no arguments are given, @command{nice} prints the current nice
+value, which it inherited.  Otherwise, @command{nice} runs the given
address@hidden with its nice value adjusted.  By default, its nice
+value is incremented by 10.
+
+Nice values range at least from @minus{}20 (resulting in the most
+favorable scheduling) through 19 (the least favorable).  Some systems
+may have a wider range of nice values; conversely, other systems may
+enforce more restrictive limits.  An attempt to set the nice value
+outside the supported range is treated as an attempt to use the
+minimum or maximum supported value.
 
 @cindex conflicts with shell built-ins
 @cindex built-in shell commands, conflicts with
-Because most shells have a built-in command by the same name, using the
+Because many shells have a built-in command by the same name, using the
 unadorned command name in a script or interactively may get you
 different functionality than that described here.
 
@@ -12030,7 +12036,10 @@ The program accepts the following option
 @itemx address@hidden
 @opindex -n
 @opindex --adjustment
-Add @var{adjustment} instead of 10 to the command's priority.
+Add @var{adjustment} instead of 10 to the command's nice value.  If
address@hidden is negative and you lack appropriate privileges,
address@hidden issues a warning but otherwise acts as if you specified
+a zero adjustment.
 
 On older systems, @command{nice} supports an obsolete option
 @address@hidden  @acronym{POSIX} 1003.1-2001 (@pxref{Standards
@@ -12053,46 +12062,47 @@ the exit status of @var{command} otherwi
 It is sometimes useful to run non-interactive programs with reduced priority.
 
 @example
-$ nice factor `echo '2^997 - 1'|bc`
+$ nice factor 4611686018427387903
 @end example
 
 Since @command{nice} prints the current priority,
-we can invoke it through itself to demonstrate how it works:
+you can invoke it through itself to demonstrate how it works.
 
-The default behavior is to reduce priority by @samp{10}.
+The default behavior is to increase the nice value by @samp{10}:
 
 @example
+$ nice
+0
 $ nice nice
 10
address@hidden example
-
address@hidden
 $ nice -n 10 nice
 10
 @end example
 
-The @var{adjustment} is relative to the current priority.
-Here, the first @command{nice} invocation runs the second one at priority
address@hidden, and it in turn runs the final one at a priority lowered by
address@hidden more.
+The @var{adjustment} is relative to the current nice value.  In the
+next example, the first @command{nice} invocation runs the second one
+with nice value 10, and it in turn runs the final one with a nice
+value that is 3 more:
 
 @example
 $ nice nice -n 3 nice
 13
 @end example
 
-Specifying a priority larger than @samp{19} is the same as specifying 
@samp{19}.
+Specifying a nice value larger than the supported range
+is the same as specifying the maximum supported value:
 
 @example
-$ nice -n 30 nice
+$ nice -n 10000000000 nice
 19
 @end example
 
-Only a privileged user may run a process with higher priority.
+Only a privileged user may run a process with higher priority:
 
 @example
 $ nice -n -1 nice
 nice: cannot set priority: Permission denied
+0
 $ sudo nice -n -1 nice
 -1
 @end example
Index: src/nice.c
===================================================================
RCS file: /home/eggert/coreutils/cu/src/nice.c,v
retrieving revision 1.75
diff -p -u -r1.75 nice.c
--- src/nice.c  21 Jan 2004 23:28:19 -0000      1.75
+++ src/nice.c  26 Jul 2004 03:21:52 -0000
@@ -44,9 +44,13 @@
 #define AUTHORS "David MacKenzie"
 
 #ifdef NICE_PRIORITY
-# define GET_PRIORITY() nice (0)
+# define GET_NICE_VALUE() nice (0)
 #else
-# define GET_PRIORITY() getpriority (PRIO_PROCESS, 0)
+# define GET_NICE_VALUE() getpriority (PRIO_PROCESS, 0)
+#endif
+
+#ifndef NZERO
+# define NZERO 20
 #endif
 
 /* The name this program was run with. */
@@ -67,13 +71,14 @@ usage (int status)
   else
     {
       printf (_("Usage: %s [OPTION] [COMMAND [ARG]...]\n"), program_name);
-      fputs (_("\
-Run COMMAND with an adjusted scheduling priority.\n\
-With no COMMAND, print the current scheduling priority.  ADJUST is 10\n\
-by default.  Range goes from -20 (highest priority) to 19 (lowest).\n\
+      printf (_("\
+Run COMMAND with an adjusted nice value, which affects the scheduling 
priority.\n\
+With no COMMAND, print the current nice value.  Nice values range from\n\
+%d (most favorable scheduling) to %d (least favorable).\n\
 \n\
-  -n, --adjustment=ADJUST   increment priority by ADJUST first\n\
-"), stdout);
+  -n, --adjustment=N   add integer N to the nice value (default 10)\n\
+"),
+             - NZERO, NZERO - 1);
       fputs (HELP_OPTION_DESCRIPTION, stdout);
       fputs (VERSION_OPTION_DESCRIPTION, stdout);
       printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
@@ -84,10 +89,10 @@ by default.  Range goes from -20 (highes
 int
 main (int argc, char **argv)
 {
-  int current_priority;
-  long int adjustment = 0;
-  int minusflag = 0;
-  int adjustment_given = 0;
+  int current_nice_value;
+  int adjustment = 10;
+  char const *adjustment_given = NULL;
+  bool ok;
   int i;
 
   initialize_main (&argc, &argv);
@@ -106,27 +111,10 @@ main (int argc, char **argv)
     {
       char *s = argv[i];
 
-      if (s[0] == '-' && s[1] == '-' && ISDIGIT (s[2])
+      if (s[0] == '-' && ISDIGIT (s[1 + (s[1] == '-' || s[1] == '+')])
          && posix2_version () < 200112)
        {
-         if (xstrtol (&s[2], NULL, 10, &adjustment, "") != LONGINT_OK)
-           error (EXIT_FAIL, 0, _("invalid option `%s'"), s);
-
-         minusflag = 1;
-         adjustment_given = 1;
-         ++i;
-       }
-      else if (s[0] == '-'
-              && (ISDIGIT (s[1]) || (s[1] == '+' && ISDIGIT (s[2])))
-              && posix2_version () < 200112)
-       {
-         if (s[1] == '+')
-           ++s;
-         if (xstrtol (&s[1], NULL, 10, &adjustment, "") != LONGINT_OK)
-           error (EXIT_FAIL, 0, _("invalid option `%s'"), s);
-
-         minusflag = 0;
-         adjustment_given = 1;
+         adjustment_given = s + 1;
          ++i;
        }
       else
@@ -146,12 +134,7 @@ main (int argc, char **argv)
                  usage (EXIT_FAIL);
 
                case 'n':
-                 if (xstrtol (optarg, NULL, 10, &adjustment, "")
-                     != LONGINT_OK)
-                   error (EXIT_FAIL, 0, _("invalid priority `%s'"), optarg);
-
-                 minusflag = 0;
-                 adjustment_given = 1;
+                 adjustment_given = optarg;
                  break;
                }
            }
@@ -163,10 +146,17 @@ main (int argc, char **argv)
        }
     }
 
-  if (minusflag)
-    adjustment = -adjustment;
-  if (!adjustment_given)
-    adjustment = 10;
+  if (adjustment_given)
+    {
+      /* If the requested adjustment is outside the valid range,
+        silently bring it to just within range; this mimics what
+        "setpriority" and "nice" do.  */
+      enum { MIN_ADJUSTMENT = 1 - 2 * NZERO, MAX_ADJUSTMENT = 2 * NZERO - 1 };
+      long int tmp;
+      if (LONGINT_OVERFLOW < xstrtol (adjustment_given, NULL, 10, &tmp, ""))
+       error (EXIT_FAIL, 0, _("invalid adjustment `%s'"), adjustment_given);
+      adjustment = MAX (MIN_ADJUSTMENT, MIN (tmp, MAX_ADJUSTMENT));
+    }
 
   if (i == argc)
     {
@@ -175,25 +165,27 @@ main (int argc, char **argv)
          error (0, 0, _("a command must be given with an adjustment"));
          usage (EXIT_FAIL);
        }
-      /* No command given; print the priority. */
+      /* No command given; print the nice value.  */
       errno = 0;
-      current_priority = GET_PRIORITY ();
-      if (current_priority == -1 && errno != 0)
+      current_nice_value = GET_NICE_VALUE ();
+      if (current_nice_value == -1 && errno != 0)
        error (EXIT_FAIL, errno, _("cannot get priority"));
-      printf ("%d\n", current_priority);
+      printf ("%d\n", current_nice_value);
       exit (EXIT_SUCCESS);
     }
 
 #ifndef NICE_PRIORITY
   errno = 0;
-  current_priority = GET_PRIORITY ();
-  if (current_priority == -1 && errno != 0)
+  current_nice_value = GET_NICE_VALUE ();
+  if (current_nice_value == -1 && errno != 0)
     error (EXIT_FAIL, errno, _("cannot get priority"));
-  if (setpriority (PRIO_PROCESS, 0, current_priority + adjustment))
+  ok = (setpriority (PRIO_PROCESS, 0, current_nice_value + adjustment) == 0);
 #else
-  if (nice (adjustment) == -1)
+  errno = 0;
+  ok = (nice (adjustment) != -1 || errno == 0);
 #endif
-    error (EXIT_FAIL, errno, _("cannot set priority"));
+  if (!ok)
+    error (errno == EPERM ? 0 : EXIT_FAIL, errno, _("cannot set priority"));
 
   execvp (argv[i], &argv[i]);
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]