core: in execute, Never fail setting Nice priority
Instead, push to the closest possible Nice priority setting. Replaces: #11397
This commit is contained in:
parent
6bbeef2042
commit
390902012c
|
@ -22,6 +22,7 @@
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "architecture.h"
|
#include "architecture.h"
|
||||||
#include "env-util.h"
|
#include "env-util.h"
|
||||||
|
#include "errno-util.h"
|
||||||
#include "escape.h"
|
#include "escape.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
|
@ -1527,6 +1528,62 @@ int pidfd_get_pid(int fd, pid_t *ret) {
|
||||||
return parse_pid(p, ret);
|
return parse_pid(p, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int rlimit_to_nice(rlim_t limit) {
|
||||||
|
if (limit <= 1)
|
||||||
|
return PRIO_MAX-1; /* i.e. 19 */
|
||||||
|
|
||||||
|
if (limit >= -PRIO_MIN + PRIO_MAX)
|
||||||
|
return PRIO_MIN; /* i.e. -20 */
|
||||||
|
|
||||||
|
return PRIO_MAX - (int) limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
int setpriority_closest(int priority) {
|
||||||
|
int current, limit, saved_errno;
|
||||||
|
struct rlimit highest;
|
||||||
|
|
||||||
|
/* Try to set requested nice level */
|
||||||
|
if (setpriority(PRIO_PROCESS, 0, priority) >= 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Permission failed */
|
||||||
|
saved_errno = -errno;
|
||||||
|
if (!ERRNO_IS_PRIVILEGE(saved_errno))
|
||||||
|
return saved_errno;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
current = getpriority(PRIO_PROCESS, 0);
|
||||||
|
if (errno != 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
if (priority == current)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Hmm, we'd expect that raising the nice level from our status quo would always work. If it doesn't,
|
||||||
|
* then the whole setpriority() system call is blocked to us, hence let's propagate the error
|
||||||
|
* right-away */
|
||||||
|
if (priority > current)
|
||||||
|
return saved_errno;
|
||||||
|
|
||||||
|
if (getrlimit(RLIMIT_NICE, &highest) < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
limit = rlimit_to_nice(highest.rlim_cur);
|
||||||
|
|
||||||
|
/* We are already less nice than limit allows us */
|
||||||
|
if (current < limit) {
|
||||||
|
log_debug("Cannot raise nice level, permissions and the resource limit do not allow it.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Push to the allowed limit */
|
||||||
|
if (setpriority(PRIO_PROCESS, 0, limit) < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
log_debug("Cannot set requested nice level (%i), used next best (%i).", priority, limit);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const char *const ioprio_class_table[] = {
|
static const char *const ioprio_class_table[] = {
|
||||||
[IOPRIO_CLASS_NONE] = "none",
|
[IOPRIO_CLASS_NONE] = "none",
|
||||||
[IOPRIO_CLASS_RT] = "realtime",
|
[IOPRIO_CLASS_RT] = "realtime",
|
||||||
|
|
|
@ -200,3 +200,5 @@ assert_cc(TASKS_MAX <= (unsigned long) PID_T_MAX);
|
||||||
})
|
})
|
||||||
|
|
||||||
int pidfd_get_pid(int fd, pid_t *ret);
|
int pidfd_get_pid(int fd, pid_t *ret);
|
||||||
|
|
||||||
|
int setpriority_closest(int priority);
|
||||||
|
|
|
@ -3236,11 +3236,11 @@ static int exec_child(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context->nice_set)
|
if (context->nice_set) {
|
||||||
if (setpriority(PRIO_PROCESS, 0, context->nice) < 0) {
|
r = setpriority_closest(context->nice);
|
||||||
*exit_status = EXIT_NICE;
|
if (r < 0)
|
||||||
return log_unit_error_errno(unit, errno, "Failed to set up process scheduling priority (nice level): %m");
|
return log_unit_error_errno(unit, r, "Failed to set up process scheduling priority (nice level): %m");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context->cpu_sched_set) {
|
if (context->cpu_sched_set) {
|
||||||
struct sched_param param = {
|
struct sched_param param = {
|
||||||
|
|
Loading…
Reference in a new issue