Prechádzať zdrojové kódy

Fix some issues with nice(). SUSv3 specifies that it return the new
priority if successful, while the linux syscall returns 0. Also, in
the non-syscall version, we must be sure to set errno to EPERM on failure
since setpriority() can set errno to several possible values.
Note: The version of glibc on my debian system is broken wrt EPERM too.

Manuel Novoa III 20 rokov pred
rodič
commit
67256bd812
1 zmenil súbory, kde vykonal 52 pridanie a 16 odobranie
  1. 52 16
      libc/sysdeps/linux/common/nice.c

+ 52 - 16
libc/sysdeps/linux/common/nice.c

@@ -3,35 +3,71 @@
  * nice() for uClibc
  *
  * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org>
+ * Copyright (C) 2005 by Manuel Novoa III <mjn3@codepoet.org>
  *
  * GNU Library General Public License (LGPL) version 2 or later.
  */
 
 #include "syscalls.h"
 #include <unistd.h>
+#include <sys/resource.h>
+
 #ifdef __NR_nice
-_syscall1(int, nice, int, inc);
+
+#define __NR___syscall_nice __NR_nice
+static inline _syscall1(int, __syscall_nice, int, incr);
+
 #else
-#include <sys/resource.h>
-int nice(int incr)
+
+#include <limits.h>
+
+static inline int int_add_no_wrap(int a, int b)
 {
-	int save, prio, result;
+	int s = a + b;
 
-	save = errno;
+	if (b < 0) {
+		if (s > a) s = INT_MIN;
+	} else {
+		if (s < a) s = INT_MAX;
+	}
+
+	return s;
+}
+
+static inline int __syscall_nice(int incr)
+{
+	int old_priority;
+#if 1
+	/* This should never fail. */
+	old_priority = getpriority(PRIO_PROCESS, 0);
+#else
+	/* But if you want to be paranoid... */
+	int old_errno;
+
+	old_errno = errno;
 	__set_errno(0);
-	prio = getpriority(PRIO_PROCESS, 0);
-	if (prio == -1) {
-		if (errno != 0) {
-			return -1;
-		} else {
-			__set_errno(save);
-		}
+	old_priority = getpriority(PRIO_PROCESS, 0);
+	if ((old_priority == -1) && errno) {
+		return -1;
 	}
-	result = setpriority(PRIO_PROCESS, 0, prio + incr);
-	if (result != -1) {
-		return prio + incr;
-	} else {
+	__set_errno(old_errno);
+#endif
+
+	if (setpriority(PRIO_PROCESS, 0, int_add_no_wrap(old_priority, incr))) {
+		__set_errno(EPERM);	/* SUSv3 mandates EPERM for nice failure. */
 		return -1;
 	}
+
+	return 0;
 }
+
 #endif
+
+int nice(int incr)
+{
+	if (__syscall_nice(incr)) {
+		return -1;
+	}
+
+	return getpriority(PRIO_PROCESS, 0);
+}