#include <errno.h>
#include <fcntl.h>
+#include <linux/limits.h>
#include <sched.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pakfire/arch.h>
+#include <pakfire/cgroup.h>
#include <pakfire/execute.h>
#include <pakfire/logging.h>
#include <pakfire/private.h>
const char** argv;
char** envp;
+ char cgroup[PATH_MAX];
+
// File descriptors
int stdout[2];
int stderr[2];
.envp = envp,
};
+ // Make cgroup name
+ snprintf(env.cgroup, sizeof(env.cgroup) - 1, "%s", "pakfire/execute-XXXXXX");
+
// Allocate stack
char stack[4096];
logging_callback = &default_logging_callback;
// Configure the new namespace
- int cflags = CLONE_VFORK | SIGCHLD | CLONE_NEWIPC | CLONE_NEWNS | CLONE_NEWUTS;
+ int cflags = CLONE_VFORK | SIGCHLD | CLONE_NEWIPC | CLONE_NEWNS | CLONE_NEWUTS
+ | CLONE_NEWCGROUP;
// Enable network?
if (!(flags & PAKFIRE_EXECUTE_ENABLE_NETWORK))
}
}
+ // Create cgroup
+ int r = pakfire_cgroup_create(pakfire, env.cgroup);
+ if (r)
+ goto ERROR;
+
// Fork this process
pid_t pid = clone(pakfire_execute_fork, stack + sizeof(stack), cflags, &env);
if (pid < 0) {
return -errno;
}
+ // Attach the process to the cgroup
+ r = pakfire_cgroup_attach(pakfire, env.cgroup, pid);
+ if (r)
+ goto ERROR;
+
// Set some useful error code
- int r = -ESRCH;
+ int exit = -ESRCH;
int status = 0;
DEBUG(pakfire, "Waiting for PID %d to finish its work\n", pid);
waitpid(pid, &status, 0);
if (WIFEXITED(status)) {
- r = WEXITSTATUS(status);
+ exit = WEXITSTATUS(status);
DEBUG(pakfire, "Child process exited with code: %d\n", r);
} else {
ERROR(pakfire, "Could not determine the exit status of process %d\n", pid);
}
+ // Kill any remaining processes in this cgroup
+ r = pakfire_cgroup_killall(pakfire, env.cgroup);
+ if (r)
+ goto ERROR;
+
+ // Return the exit code of the application
+ r = exit;
+
+ERROR:
+ // Destroy the cgroup
+ pakfire_cgroup_destroy(pakfire, env.cgroup);
+
// Close any file descriptors
if (env.stdout[0])
close(env.stdout[0]);