0

Why would os.nice(10) fail with OSError: [Errno 1] Operation not permitted on OS X? Running from a standard user account:

$ python
…
>>> os.nice(10)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 1] Operation not permitted

Details:

  • Python 2.7.2
  • OS X 10.8.4
David Wolever
  • 148,955
  • 89
  • 346
  • 502
  • 1
    Maybe the process is already running with a higher nice level. Check with `ps` to see what `nice` level your process is running with. – nneonneo Sep 10 '14 at 19:24
  • Ah, that's it! I forgot that I'd nice'd down the terminal a couple of days ago, and didn't realize it was an error to nice up past 20. – David Wolever Sep 10 '14 at 19:29

2 Answers2

4

As pointed out by Lukas Graf, os.nice increments the nice level, rather than setting it.

This appears to instead be an OS X bug, which is triggered if you call nice while sitting at a nice priority of 20 or higher:

nice -n 20 python -c 'import os; os.nice(10)'

fails, while

nice -n 19 python -c 'import os; os.nice(10)'

works. A simple C program exhibits the same problem:

#include <unistd.h>
#include <string.h>

int main() {
    if(nice(10) < 0)
        perror("nice");
}

prints an error if you run it as nice -n 20 ./test, but succeeds if it is run as nice -n 19 ./test.


The reason is because a nice level of 20 is above the maximum nice level supported by the nice API (NZERO). OS X's nice utility uses setpriority so it ignores the limit, but the nice C function (which is used directly by Python) does care. If the process priority is 20 or above, nice will attempt to set the priority to 19 which is not allowed (since it would increase the process priority, which only a privileged user can do).

This is a weird bug, but it can easily be avoided by never using a process priority of 20.

nneonneo
  • 171,345
  • 36
  • 312
  • 383
  • Err, disregard the previous comment. Python's behavior is correct. It is just an error to nice up past 20. – David Wolever Sep 10 '14 at 19:43
  • @nneonneo sorry, I deleted my comment because after writing it, I observed behavior that seems to contradict it: With my `python` starting at nice `0`, I can call `os.nice(10)` repeatedly, and it never errors, always increments by a relative amount, and caps at `19`. However, a single `os.nice(-1)` always results in `Operation not permitted`, irrespective of any preconditions. – Lukas Graf Sep 10 '14 at 20:11
  • @LukasGraf: Yeah, that's because `os.nice(-1)` is asking for an "increment" of -1, which by definition would decrease the niceness. – nneonneo Sep 10 '14 at 20:12
  • @nneonneo yeah, but shouldn't I be allowed to do that for my own processes? – Lukas Graf Sep 10 '14 at 20:12
  • (I don't completely remember your comment, but I do remember that it pointed out that `os.nice` was an increment, a detail that I completely overlooked.) – nneonneo Sep 10 '14 at 20:12
  • @LukasGraf: no, that would allow a nobody user to make his processes high-priority. Processes aren't permitted to raise their own priority unless they are privileged (i.e. are running as root). – nneonneo Sep 10 '14 at 20:13
1

Check what your PRIO_MAX is and which nicenesses are allowed to be used by non super-users

Users other than the super-user may only alter the priority of processes they own, and can only mono-tonically monotonically tonically increase their ``nice value'' within the range 0 to PRIO_MAX (20).

https://developer.apple.com/library/mac/documentation/Darwin/Reference/Manpages/man8/renice.8.html