PAKFIRE_EXPORT int pakfire_execute(struct pakfire* pakfire, const char* argv[], char* envp[],
int flags, pakfire_execute_logging_callback logging_callback, void* data) {
- DIR* cgroupdir = NULL;
int r;
struct pakfire_execute env = {
.pakfire = pakfire,
.argv = argv,
- .cgroup = "pakfire/execute-XXXXXX",
};
// argv is invalid
CLONE_NEWIPC |
CLONE_NEWNS |
CLONE_NEWPID |
- CLONE_NEWUTS |
- CLONE_INTO_CGROUP,
+ CLONE_NEWUTS,
.exit_signal = SIGCHLD,
};
}
}
- // Make cgroup name
- r = pakfire_cgroup_random_name(env.cgroup);
- if (r)
- goto ERROR;
-
- // Create cgroup
- r = pakfire_cgroup_create(pakfire, env.cgroup);
- if (r) {
- ERROR(pakfire, "Could not create cgroup %s: %m\n", env.cgroup);
- goto ERROR;
- }
-
- // Launch the new process straight into their cgroup
- cgroupdir = pakfire_cgroup_opendir(pakfire, env.cgroup);
- if (!cgroupdir) {
- ERROR(pakfire, "Could not open cgroup %s: %m\n", env.cgroup);
- goto ERROR;
- }
-
- // Clone into this cgroup
- args.cgroup = dirfd(cgroupdir);
-
// Fork this process
pid_t pid = clone3(&args, sizeof(args));
if (pid < 0) {
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;
-
- struct pakfire_cgroup_cpustat cpustat;
-
- // Fetch CPU usage stats
- r = pakfire_cgroup_cpustat(pakfire, env.cgroup, &cpustat);
- if (r) {
- ERROR(pakfire, "Could not read CPU usage stats: %m\n");
- r = -1;
- goto ERROR;
- }
-
- // Log CPU usage stats
- DEBUG(pakfire, "cgroup %s used %.4fs of CPU time\n", env.cgroup,
- (double)(cpustat.usage.tv_sec) + ((double)cpustat.usage.tv_usec / 1000000));
-
// Return the exit code of the application
r = exit;
ERROR:
- // Close the cgroup
- if (cgroupdir)
- closedir(cgroupdir);
-
- // Destroy the cgroup
- pakfire_cgroup_destroy(pakfire, env.cgroup);
-
// Close any file descriptors
if (env.stdout[0])
close(env.stdout[0]);