From: Michael Tremer Date: Wed, 3 Aug 2022 15:58:08 +0000 (+0000) Subject: jail: Implement setting nice level X-Git-Tag: 0.9.28~595 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cf440db8cc1976abc809ead342b8466ba58488f3;p=pakfire.git jail: Implement setting nice level Signed-off-by: Michael Tremer --- diff --git a/src/_pakfire/pakfire.c b/src/_pakfire/pakfire.c index d3323527d..1d14df47d 100644 --- a/src/_pakfire/pakfire.c +++ b/src/_pakfire/pakfire.c @@ -822,6 +822,7 @@ static PyObject* Pakfire_execute(PakfireObject* self, PyObject* args, PyObject* "enable_network", "interactive", "logging_callback", + "nice", NULL }; @@ -836,9 +837,10 @@ static PyObject* Pakfire_execute(PakfireObject* self, PyObject* args, PyObject* int enable_network = 0; int interactive = 0; PyObject* logging_callback = NULL; + int nice = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OppO", kwlist, &command, &environ, - &enable_network, &interactive, &logging_callback)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OppOi", kwlist, &command, &environ, + &enable_network, &interactive, &logging_callback, &nice)) return NULL; // Check if command is a list @@ -900,6 +902,15 @@ static PyObject* Pakfire_execute(PakfireObject* self, PyObject* args, PyObject* pakfire_jail_set_log_callback(jail, __Pakfire_logging_callback, logging_callback); } + // Set nice + if (nice) { + r = pakfire_jail_nice(jail, nice); + if (r) { + PyErr_SetFromErrno(PyExc_OSError); + goto ERROR; + } + } + PyObject* key = NULL; PyObject* value = NULL; Py_ssize_t p = 0; diff --git a/src/libpakfire/include/pakfire/jail.h b/src/libpakfire/include/pakfire/jail.h index 9edd5b426..9468af0a9 100644 --- a/src/libpakfire/include/pakfire/jail.h +++ b/src/libpakfire/include/pakfire/jail.h @@ -42,6 +42,9 @@ struct pakfire_jail* pakfire_jail_unref(struct pakfire_jail* jail); int pakfire_jail_set_log_callback(struct pakfire_jail* jail, pakfire_jail_log_callback callback, void* data); +// Resource Limits +int pakfire_jail_nice(struct pakfire_jail* jail, int nice); + // Environment const char* pakfire_jail_get_env(struct pakfire_jail* jail, const char* key); int pakfire_jail_set_env(struct pakfire_jail* jail, const char* key, const char* value); diff --git a/src/libpakfire/jail.c b/src/libpakfire/jail.c index eee2289ad..4a3fe004b 100644 --- a/src/libpakfire/jail.c +++ b/src/libpakfire/jail.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -67,6 +68,9 @@ struct pakfire_jail { // Flags int flags; + // Resource Limits + int nice; + // Environment char* env[ENVIRON_SIZE]; @@ -226,6 +230,21 @@ static int pakfire_jail_has_flag(struct pakfire_jail* jail, int flag) { return jail->flags & flag; } +// Resource Limits + +PAKFIRE_EXPORT int pakfire_jail_nice(struct pakfire_jail* jail, int nice) { + // Check if nice level is in range + if (nice < -19 || nice > 20) { + errno = EINVAL; + return 1; + } + + // Store nice level + jail->nice = nice; + + return 0; +} + // Environment // Returns the length of the environment @@ -930,7 +949,10 @@ static int pakfire_jail_child(struct pakfire_jail* jail, struct pakfire_jail_exe // XXX do we have to reconfigure logging here? - DEBUG(jail->pakfire, "Launched child process in jail with PID %d\n", getpid()); + // Fetch my own PID + pid_t pid = getpid(); + + DEBUG(jail->pakfire, "Launched child process in jail with PID %d\n", pid); // Wait for the parent to finish initialization r = pakfire_jail_wait_for_signal(jail, ctx->completed_fd); @@ -994,6 +1016,17 @@ static int pakfire_jail_child(struct pakfire_jail* jail, struct pakfire_jail_exe } } + // Set nice level + if (jail->nice) { + DEBUG(jail->pakfire, "Setting nice level to %d\n", jail->nice); + + r = setpriority(PRIO_PROCESS, pid, jail->nice); + if (r) { + ERROR(jail->pakfire, "Could not set nice level: %m\n"); + return 1; + } + } + // Reset open file limit (http://0pointer.net/blog/file-descriptor-limits.html) r = pakfire_rlimit_reset_nofile(jail->pakfire); if (r) diff --git a/src/libpakfire/libpakfire.sym b/src/libpakfire/libpakfire.sym index ed0d4c14f..ab694b3c6 100644 --- a/src/libpakfire/libpakfire.sym +++ b/src/libpakfire/libpakfire.sym @@ -138,6 +138,7 @@ global: pakfire_jail_exec_script; pakfire_jail_get_env; pakfire_jail_import_env; + pakfire_jail_nice; pakfire_jail_ref; pakfire_jail_set_env; pakfire_jail_set_log_callback; diff --git a/tests/python/execute.py b/tests/python/execute.py index 4de96f4e4..29b373802 100755 --- a/tests/python/execute.py +++ b/tests/python/execute.py @@ -106,6 +106,17 @@ class Test(unittest.TestCase): self.pakfire.execute(["/command", "pid"], logging_callback=checkpid) + def test_nice(self): + self.pakfire.execute(["/command", "print-nice"], nice=5) + + def test_nice_invalid_input(self): + """ + Tries using an invalid nice value + """ + with self.assertRaises(OSError): + self.pakfire.execute(["/command", "print-nice"], nice=100) + + # This is an interactive test which cannot be performed automatically #def test_shell(self): # self.pakfire.execute(["/bin/bash", "-i"]) diff --git a/tests/stub/command.c b/tests/stub/command.c index 6ee1f20b7..53b0714b9 100644 --- a/tests/stub/command.c +++ b/tests/stub/command.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -165,6 +166,15 @@ static int pid(int argc, char* argv[]) { return 0; } +static int print_nice(int argc, char* argv[]) { + int nice = getpriority(PRIO_PROCESS, 0); + + // Print the nice level + printf("%d\n", nice); + + return 0; +} + int main(int argc, char* argv[]) { if (argc < 2) { fprintf(stderr, "No command given\n"); @@ -202,6 +212,10 @@ int main(int argc, char* argv[]) { else if (strcmp(command, "pid") == 0) callback = pid; + // Print nice level + else if (strcmp(command, "print-nice") == 0) + callback = print_nice; + // Exit if no callback has been set if (!callback) { fprintf(stderr, "Unknown command: %s\n", command);