mirror of
https://github.com/systemd/systemd.git
synced 2025-03-31 14:50:15 +03:00
shutdown: execute all binaries in /lib/systemd/system-shutdown as last step before invoking reboot()
This commit is contained in:
parent
3036c489fa
commit
83cc030fad
@ -41,6 +41,7 @@ rootsbindir=$(rootdir)/sbin
|
||||
rootlibexecdir=$(rootdir)/lib/systemd
|
||||
systemunitdir=$(rootdir)/lib/systemd/system
|
||||
systemgeneratordir=$(rootdir)/lib/systemd/system-generators
|
||||
systemshutdowndir=$(rootdir)/lib/systemd/system-shutdown
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-include $(top_builddir)/config.h \
|
||||
@ -62,6 +63,7 @@ AM_CPPFLAGS = \
|
||||
-DSYSTEMD_CRYPTSETUP_PATH=\"$(rootlibexecdir)/systemd-cryptsetup\" \
|
||||
-DSYSTEM_GENERATOR_PATH=\"$(systemgeneratordir)\" \
|
||||
-DUSER_GENERATOR_PATH=\"$(usergeneratordir)\" \
|
||||
-DSYSTEM_SHUTDOWN_PATH=\"$(systemshutdowndir)\" \
|
||||
-I $(top_srcdir)/src
|
||||
|
||||
if TARGET_GENTOO
|
||||
@ -375,7 +377,8 @@ libsystemd_basic_la_SOURCES = \
|
||||
src/conf-parser.c \
|
||||
src/socket-util.c \
|
||||
src/log.c \
|
||||
src/ratelimit.c
|
||||
src/ratelimit.c \
|
||||
src/exit-status.c
|
||||
|
||||
libsystemd_basic_la_CFLAGS = \
|
||||
$(AM_CFLAGS) \
|
||||
@ -403,7 +406,6 @@ libsystemd_core_la_SOURCES = \
|
||||
src/load-dropin.c \
|
||||
src/execute.c \
|
||||
src/utmp-wtmp.c \
|
||||
src/exit-status.c \
|
||||
src/dbus.c \
|
||||
src/dbus-manager.c \
|
||||
src/dbus-unit.c \
|
||||
|
@ -2836,9 +2836,8 @@ void manager_check_finished(Manager *m) {
|
||||
|
||||
void manager_run_generators(Manager *m) {
|
||||
DIR *d = NULL;
|
||||
struct dirent *de;
|
||||
Hashmap *pids = NULL;
|
||||
const char *generator_path;
|
||||
const char *argv[3];
|
||||
|
||||
assert(m);
|
||||
|
||||
@ -2868,83 +2867,11 @@ void manager_run_generators(Manager *m) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!(pids = hashmap_new(trivial_hash_func, trivial_compare_func))) {
|
||||
log_error("Failed to allocate set.");
|
||||
goto finish;
|
||||
}
|
||||
argv[0] = NULL; /* Leave this empty, execute_directory() will fill something in */
|
||||
argv[1] = m->generator_unit_path;
|
||||
argv[2] = NULL;
|
||||
|
||||
while ((de = readdir(d))) {
|
||||
char *path;
|
||||
pid_t pid;
|
||||
int k;
|
||||
|
||||
if (ignore_file(de->d_name))
|
||||
continue;
|
||||
|
||||
if (de->d_type != DT_REG &&
|
||||
de->d_type != DT_LNK &&
|
||||
de->d_type != DT_UNKNOWN)
|
||||
continue;
|
||||
|
||||
if (asprintf(&path, "%s/%s", generator_path, de->d_name) < 0) {
|
||||
log_error("Out of memory");
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((pid = fork()) < 0) {
|
||||
log_error("Failed to fork: %m");
|
||||
free(path);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
const char *arguments[5];
|
||||
/* Child */
|
||||
|
||||
arguments[0] = path;
|
||||
arguments[1] = m->generator_unit_path;
|
||||
arguments[2] = NULL;
|
||||
|
||||
execv(path, (char **) arguments);
|
||||
|
||||
log_error("Failed to execute %s: %m", path);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
log_debug("Spawned generator %s as %lu", path, (unsigned long) pid);
|
||||
|
||||
if ((k = hashmap_put(pids, UINT_TO_PTR(pid), path)) < 0) {
|
||||
log_error("Failed to add PID to set: %s", strerror(-k));
|
||||
free(path);
|
||||
}
|
||||
}
|
||||
|
||||
while (!hashmap_isempty(pids)) {
|
||||
siginfo_t si;
|
||||
char *path;
|
||||
|
||||
zero(si);
|
||||
if (waitid(P_ALL, 0, &si, WEXITED) < 0) {
|
||||
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
|
||||
log_error("waitid() failed: %m");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if ((path = hashmap_remove(pids, UINT_TO_PTR(si.si_pid)))) {
|
||||
if (!is_clean_exit(si.si_code, si.si_status)) {
|
||||
if (si.si_code == CLD_EXITED)
|
||||
log_error("%s exited with exit status %i.", path, si.si_status);
|
||||
else
|
||||
log_error("%s terminated by signal %s.", path, signal_to_string(si.si_status));
|
||||
} else
|
||||
log_debug("Generator %s exited successfully.", path);
|
||||
|
||||
free(path);
|
||||
}
|
||||
}
|
||||
execute_directory(generator_path, d, (char**) argv);
|
||||
|
||||
if (rmdir(m->generator_unit_path) >= 0) {
|
||||
/* Uh? we were able to remove this dir? I guess that
|
||||
@ -2973,9 +2900,6 @@ void manager_run_generators(Manager *m) {
|
||||
finish:
|
||||
if (d)
|
||||
closedir(d);
|
||||
|
||||
if (pids)
|
||||
hashmap_free_free(pids);
|
||||
}
|
||||
|
||||
void manager_undo_generators(Manager *m) {
|
||||
|
@ -336,6 +336,8 @@ int main(int argc, char *argv[]) {
|
||||
if (retries >= FINALIZE_ATTEMPTS)
|
||||
log_error("Too many interations, giving up.");
|
||||
|
||||
execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, NULL);
|
||||
|
||||
sync();
|
||||
|
||||
if (cmd == LINUX_REBOOT_CMD_KEXEC) {
|
||||
|
114
src/util.c
114
src/util.c
@ -59,6 +59,7 @@
|
||||
#include "strv.h"
|
||||
#include "label.h"
|
||||
#include "exit-status.h"
|
||||
#include "hashmap.h"
|
||||
|
||||
bool streq_ptr(const char *a, const char *b) {
|
||||
|
||||
@ -3664,6 +3665,119 @@ bool running_in_vm(void) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void execute_directory(const char *directory, DIR *d, char *argv[]) {
|
||||
DIR *_d = NULL;
|
||||
struct dirent *de;
|
||||
Hashmap *pids = NULL;
|
||||
|
||||
assert(directory);
|
||||
|
||||
/* Executes all binaries in a directory in parallel and waits
|
||||
* until all they all finished. */
|
||||
|
||||
if (!d) {
|
||||
if (!(_d = opendir(directory))) {
|
||||
|
||||
if (errno == ENOENT)
|
||||
return;
|
||||
|
||||
log_error("Failed to enumerate directory %s: %m", directory);
|
||||
return;
|
||||
}
|
||||
|
||||
d = _d;
|
||||
}
|
||||
|
||||
if (!(pids = hashmap_new(trivial_hash_func, trivial_compare_func))) {
|
||||
log_error("Failed to allocate set.");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
while ((de = readdir(d))) {
|
||||
char *path;
|
||||
pid_t pid;
|
||||
int k;
|
||||
|
||||
if (ignore_file(de->d_name))
|
||||
continue;
|
||||
|
||||
if (de->d_type != DT_REG &&
|
||||
de->d_type != DT_LNK &&
|
||||
de->d_type != DT_UNKNOWN)
|
||||
continue;
|
||||
|
||||
if (asprintf(&path, "%s/%s", directory, de->d_name) < 0) {
|
||||
log_error("Out of memory");
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((pid = fork()) < 0) {
|
||||
log_error("Failed to fork: %m");
|
||||
free(path);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
char *_argv[2];
|
||||
/* Child */
|
||||
|
||||
if (!argv) {
|
||||
_argv[0] = path;
|
||||
_argv[1] = NULL;
|
||||
argv = _argv;
|
||||
} else
|
||||
if (!argv[0])
|
||||
argv[0] = path;
|
||||
|
||||
execv(path, argv);
|
||||
|
||||
log_error("Failed to execute %s: %m", path);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
log_debug("Spawned %s as %lu", path, (unsigned long) pid);
|
||||
|
||||
if ((k = hashmap_put(pids, UINT_TO_PTR(pid), path)) < 0) {
|
||||
log_error("Failed to add PID to set: %s", strerror(-k));
|
||||
free(path);
|
||||
}
|
||||
}
|
||||
|
||||
while (!hashmap_isempty(pids)) {
|
||||
siginfo_t si;
|
||||
char *path;
|
||||
|
||||
zero(si);
|
||||
if (waitid(P_ALL, 0, &si, WEXITED) < 0) {
|
||||
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
|
||||
log_error("waitid() failed: %m");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if ((path = hashmap_remove(pids, UINT_TO_PTR(si.si_pid)))) {
|
||||
if (!is_clean_exit(si.si_code, si.si_status)) {
|
||||
if (si.si_code == CLD_EXITED)
|
||||
log_error("%s exited with exit status %i.", path, si.si_status);
|
||||
else
|
||||
log_error("%s terminated by signal %s.", path, signal_to_string(si.si_status));
|
||||
} else
|
||||
log_debug("%s exited successfully.", path);
|
||||
|
||||
free(path);
|
||||
}
|
||||
}
|
||||
|
||||
finish:
|
||||
if (_d)
|
||||
closedir(_d);
|
||||
|
||||
if (pids)
|
||||
hashmap_free_free(pids);
|
||||
}
|
||||
|
||||
static const char *const ioprio_class_table[] = {
|
||||
[IOPRIO_CLASS_NONE] = "none",
|
||||
[IOPRIO_CLASS_RT] = "realtime",
|
||||
|
@ -375,6 +375,8 @@ const char *default_term_for_tty(const char *tty);
|
||||
|
||||
bool running_in_vm(void);
|
||||
|
||||
void execute_directory(const char *directory, DIR *_d, char *argv[]);
|
||||
|
||||
#define NULSTR_FOREACH(i, l) \
|
||||
for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user