]> git.ipfire.org Git - pakfire.git/commitdiff
jail: Implement setting nice level
authorMichael Tremer <michael.tremer@ipfire.org>
Wed, 3 Aug 2022 15:58:08 +0000 (15:58 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Wed, 3 Aug 2022 15:58:08 +0000 (15:58 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/_pakfire/pakfire.c
src/libpakfire/include/pakfire/jail.h
src/libpakfire/jail.c
src/libpakfire/libpakfire.sym
tests/python/execute.py
tests/stub/command.c

index d3323527d8461f02d2b78899566785745dfdd721..1d14df47d6fcaae00a38cc3ff4eda4b89e47ef9c 100644 (file)
@@ -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;
index 9edd5b42663291b167732300c785edaa299119ab..9468af0a918b97e122ce7f2b9c76f1de13263d57 100644 (file)
@@ -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);
index eee2289ad288900a972fc8ecf99ef2e1d16320d4..4a3fe004b98a18486d76c298701d92245fbb85f3 100644 (file)
@@ -32,6 +32,7 @@
 #include <sys/eventfd.h>
 #include <sys/personality.h>
 #include <sys/prctl.h>
+#include <sys/resource.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 
@@ -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)
index ed0d4c14ff83275ebcc229e7dda1a299cae9a869..ab694b3c6f420587b78666ed31b8738240cec51e 100644 (file)
@@ -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;
index 4de96f4e45a27d414ae13c98f45aad267dd7e551..29b373802920bc05b55b2d131d9f7d08a6e7855f 100755 (executable)
@@ -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"])
index 6ee1f20b72870ad474b6a8f1723f30c8b96d9f24..53b0714b97e557dc1e3761e7094aedddb037d727 100644 (file)
@@ -21,6 +21,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/resource.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <time.h>
@@ -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);