]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
chrt: follow nice setting, prefer sched_setscheduler()
authorKarel Zak <kzak@redhat.com>
Mon, 3 Oct 2016 09:02:35 +0000 (11:02 +0200)
committerKarel Zak <kzak@redhat.com>
Mon, 3 Oct 2016 09:02:35 +0000 (11:02 +0200)
* do not reset 'nice' setting by sched_setattr(), if 'nice' setting
  is not zero then chrt ends with EPERM for non-root users:

  $ renice -n 5 -p $$; chrt -v -b 0 date
  12475 (process ID) old priority 0, new priority 5
  chrt: failed to set pid 0's policy: Operation not permitted

* it seems more elegant to always use old sched_setscheduler() API for
  non-deadline policies; in this case we do not need getpriority()
  to keep 'nice' unchanged.

Addresses: https://github.com/karelzak/util-linux/issues/359
Signed-off-by: Karel Zak <kzak@redhat.com>
schedutils/chrt.c

index edae0d9f4898922f318522871668142f1de798f2..0a51c1088ca78e89e078b82304a17f1da32b8e9b 100644 (file)
@@ -26,6 +26,8 @@
 #include <unistd.h>
 #include <getopt.h>
 #include <errno.h>
+#include <sys/time.h>
+#include <sys/resource.h>
 
 #include "c.h"
 #include "nls.h"
@@ -340,6 +342,7 @@ static int set_sched_one_by_setscheduler(struct chrt_ctl *ctl, pid_t pid)
        struct sched_param sp = { .sched_priority = ctl->priority };
        int policy = ctl->policy;
 
+       errno = 0;
 # ifdef SCHED_RESET_ON_FORK
        if (ctl->reset_on_fork)
                policy |= SCHED_RESET_ON_FORK;
@@ -357,29 +360,28 @@ static int set_sched_one(struct chrt_ctl *ctl, pid_t pid)
 #else /* !HAVE_SCHED_SETATTR */
 static int set_sched_one(struct chrt_ctl *ctl, pid_t pid)
 {
+       struct sched_attr sa = { .size = sizeof(struct sched_attr) };
+
+       /* old API is good enough for non-deadline */
+       if (ctl->policy != SCHED_DEADLINE)
+               return set_sched_one_by_setscheduler(ctl, pid);
+
+       /* no changeed by chrt, follow the current setting */
+       sa.sched_nice = getpriority(PRIO_PROCESS, pid);
+
        /* use main() to check if the setting makes sense */
-       struct sched_attr sa = {
-               .size           = sizeof(struct sched_attr),
-               .sched_policy   = ctl->policy,
-               .sched_priority = ctl->priority,
-               .sched_runtime  = ctl->runtime,
-               .sched_period   = ctl->period,
-               .sched_deadline = ctl->deadline
-       };
-       int rc;
+       sa.sched_policy   = ctl->policy;
+       sa.sched_priority = ctl->priority;
+       sa.sched_runtime  = ctl->runtime;
+       sa.sched_period   = ctl->period;
+       sa.sched_deadline = ctl->deadline;
 
 # ifdef SCHED_RESET_ON_FORK
        if (ctl->reset_on_fork)
                sa.sched_flags |= SCHED_RESET_ON_FORK;
 # endif
        errno = 0;
-       rc = sched_setattr(pid, &sa, 0);
-
-       if (rc != 0 && errno == ENOSYS && ctl->policy != SCHED_DEADLINE)
-               /* fallback -- build with new kernel/libc, but executed on old kernels */
-               rc = set_sched_one_by_setscheduler(ctl, pid);
-
-       return rc;
+       return sched_setattr(pid, &sa, 0);
 }
 #endif /* HAVE_SCHED_SETATTR */