197 lines
6.5 KiB
Diff
197 lines
6.5 KiB
Diff
|
From b7dd2a9e5973544f248aeeb7bc0b5e7afbd27d9b Mon Sep 17 00:00:00 2001
|
||
|
From: Zdenek Kabelac <zkabelac@redhat.com>
|
||
|
Date: Mon, 25 Sep 2023 13:07:00 +0200
|
||
|
Subject: [PATCH 137/139] dmeventd: implement exit_on file check
|
||
|
|
||
|
When exit on file is present in a system and term/break signal is
|
||
|
catched, them dmeventd is no longger refusing to exit.
|
||
|
|
||
|
For the correct shutdown, there should be ideally unmonitoring call,
|
||
|
however in some case it's very hard to implement this correct procedure.
|
||
|
|
||
|
With this 'exit on' file dmeventd at least avoid 'blocking' shutdown,
|
||
|
before systemd kills use with -9 anyway possibly even in some unwanted
|
||
|
stated of internal dmeventd processing (i.e. in the middle of some lvm
|
||
|
command processing).
|
||
|
|
||
|
(cherry picked from commit a9d7a9d1289d7cafa1db5fd1e41417bf4f7709d1)
|
||
|
---
|
||
|
daemons/dmeventd/dmeventd.c | 57 ++++++++++++++++++++++++++++---------
|
||
|
make.tmpl.in | 1 +
|
||
|
man/Makefile.in | 1 +
|
||
|
man/dmeventd.8_main | 12 ++++++++
|
||
|
4 files changed, 58 insertions(+), 13 deletions(-)
|
||
|
|
||
|
diff --git a/daemons/dmeventd/dmeventd.c b/daemons/dmeventd/dmeventd.c
|
||
|
index 46c34ada2..828bc0c7a 100644
|
||
|
--- a/daemons/dmeventd/dmeventd.c
|
||
|
+++ b/daemons/dmeventd/dmeventd.c
|
||
|
@@ -98,6 +98,7 @@ static int _systemd_activation = 0;
|
||
|
static int _foreground = 0;
|
||
|
static int _restart = 0;
|
||
|
static time_t _idle_since = 0;
|
||
|
+static const char *_exit_on = DEFAULT_DMEVENTD_EXIT_ON_PATH;
|
||
|
static char **_initial_registrations = 0;
|
||
|
|
||
|
/* FIXME Make configurable at runtime */
|
||
|
@@ -723,12 +724,18 @@ static int _get_status(struct message_data *message_data)
|
||
|
static int _get_parameters(struct message_data *message_data) {
|
||
|
struct dm_event_daemon_message *msg = message_data->msg;
|
||
|
int size;
|
||
|
+ char idle_buf[32] = "";
|
||
|
+
|
||
|
+ if (_idle_since)
|
||
|
+ (void)dm_snprintf(idle_buf, sizeof(idle_buf), " idle=%lu", (long unsigned) (time(NULL) - _idle_since));
|
||
|
|
||
|
free(msg->data);
|
||
|
- if ((size = dm_asprintf(&msg->data, "%s pid=%d daemon=%s exec_method=%s",
|
||
|
+ if ((size = dm_asprintf(&msg->data, "%s pid=%d daemon=%s exec_method=%s exit_on=\"%s\"%s",
|
||
|
message_data->id, getpid(),
|
||
|
_foreground ? "no" : "yes",
|
||
|
- _systemd_activation ? "systemd" : "direct")) < 0) {
|
||
|
+ _systemd_activation ? "systemd" : "direct",
|
||
|
+ _exit_on,
|
||
|
+ idle_buf)) < 0) {
|
||
|
stack;
|
||
|
return -ENOMEM;
|
||
|
}
|
||
|
@@ -2240,8 +2247,9 @@ bad:
|
||
|
static void _usage(char *prog, FILE *file)
|
||
|
{
|
||
|
fprintf(file, "Usage:\n"
|
||
|
- "%s [-d [-d [-d]]] [-f] [-h] [i] [-l] [-R] [-V] [-?]\n\n"
|
||
|
+ "%s [-d [-d [-d]]] [-e path] [-f] [-h] [i] [-l] [-R] [-V] [-?]\n\n"
|
||
|
" -d Log debug messages to syslog (-d, -dd, -ddd)\n"
|
||
|
+ " -e Select a file path checked on exit\n"
|
||
|
" -f Don't fork, run in the foreground\n"
|
||
|
" -h Show this help information\n"
|
||
|
" -i Query running instance of dmeventd for info\n"
|
||
|
@@ -2264,7 +2272,7 @@ int main(int argc, char *argv[])
|
||
|
|
||
|
optopt = optind = opterr = 0;
|
||
|
optarg = (char*) "";
|
||
|
- while ((opt = getopt(argc, argv, "?fhiVdlR")) != EOF) {
|
||
|
+ while ((opt = getopt(argc, argv, ":?e:fhiVdlR")) != EOF) {
|
||
|
switch (opt) {
|
||
|
case 'h':
|
||
|
_usage(argv[0], stdout);
|
||
|
@@ -2277,6 +2285,13 @@ int main(int argc, char *argv[])
|
||
|
case 'R':
|
||
|
_restart++;
|
||
|
break;
|
||
|
+ case 'e':
|
||
|
+ if (strchr(optarg, '"')) {
|
||
|
+ fprintf(stderr, "dmeventd: option -e does not accept path \"%s\" with '\"' character.\n", optarg);
|
||
|
+ return EXIT_FAILURE;
|
||
|
+ }
|
||
|
+ _exit_on=optarg;
|
||
|
+ break;
|
||
|
case 'f':
|
||
|
_foreground++;
|
||
|
break;
|
||
|
@@ -2289,6 +2304,9 @@ int main(int argc, char *argv[])
|
||
|
case 'V':
|
||
|
printf("dmeventd version: %s\n", DM_LIB_VERSION);
|
||
|
return EXIT_SUCCESS;
|
||
|
+ case ':':
|
||
|
+ fprintf(stderr, "dmeventd: option -%c requires an argument.\n", optopt);
|
||
|
+ return EXIT_FAILURE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@@ -2379,15 +2397,28 @@ int main(int argc, char *argv[])
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
- } else if (_exit_now == DM_SIGNALED_EXIT) {
|
||
|
- _exit_now = DM_SCHEDULED_EXIT;
|
||
|
- /*
|
||
|
- * When '_exit_now' is set, signal has been received,
|
||
|
- * but can not simply exit unless all
|
||
|
- * threads are done processing.
|
||
|
- */
|
||
|
- log_info("dmeventd received break, scheduling exit.");
|
||
|
- }
|
||
|
+ } else
|
||
|
+ switch (_exit_now) {
|
||
|
+ case DM_SIGNALED_EXIT:
|
||
|
+ _exit_now = DM_SCHEDULED_EXIT;
|
||
|
+ /*
|
||
|
+ * When '_exit_now' is set, signal has been received,
|
||
|
+ * but can not simply exit unless all
|
||
|
+ * threads are done processing.
|
||
|
+ */
|
||
|
+ log_info("dmeventd received break, scheduling exit.");
|
||
|
+ /* fall through */
|
||
|
+ case DM_SCHEDULED_EXIT:
|
||
|
+ /* While exit is scheduled, check for exit_on file */
|
||
|
+ DEBUGLOG("Checking exit on file \"%s\".", _exit_on);
|
||
|
+ if (_exit_on[0] && (access(_exit_on, F_OK) == 0)) {
|
||
|
+ log_info("dmeventd detected exit on file %s, unregistering all monitored devices.",
|
||
|
+ _exit_on);
|
||
|
+ _unregister_all_threads();
|
||
|
+ }
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
_process_request(&fifos);
|
||
|
_cleanup_unused_threads();
|
||
|
}
|
||
|
diff --git a/make.tmpl.in b/make.tmpl.in
|
||
|
index 7799a8adb..99170ca7f 100644
|
||
|
--- a/make.tmpl.in
|
||
|
+++ b/make.tmpl.in
|
||
|
@@ -147,6 +147,7 @@ DEFAULT_LOCK_DIR = @DEFAULT_LOCK_DIR@
|
||
|
DEFAULT_RUN_DIR = @DEFAULT_RUN_DIR@
|
||
|
DEFAULT_PID_DIR = @DEFAULT_PID_DIR@
|
||
|
DEFAULT_MANGLING = @MANGLING@
|
||
|
+DEFAULT_DMEVENTD_EXIT_ON_PATH = @DEFAULT_DMEVENTD_EXIT_ON_PATH@
|
||
|
|
||
|
# Setup vpath search paths for some suffixes
|
||
|
vpath %.c $(srcdir)
|
||
|
diff --git a/man/Makefile.in b/man/Makefile.in
|
||
|
index ba6f2046f..f324150de 100644
|
||
|
--- a/man/Makefile.in
|
||
|
+++ b/man/Makefile.in
|
||
|
@@ -181,6 +181,7 @@ $(SED) -e "s+#VERSION#+$(LVM_VERSION)+" \
|
||
|
-e "s+#DEFAULT_PID_DIR#+$(DEFAULT_PID_DIR)+" \
|
||
|
-e "s+#SYSTEMD_GENERATOR_DIR#+$(SYSTEMD_GENERATOR_DIR)+" \
|
||
|
-e "s+#DEFAULT_LIBLINE#+$(DEFAULT_LIBLINE)+" \
|
||
|
+ -e "s+#DEFAULT_DMEVENTD_EXIT_ON_PATH#+$(DEFAULT_DMEVENTD_EXIT_ON_PATH)+" \
|
||
|
-e "s+#DEFAULT_MANGLING#+$(DEFAULT_MANGLING)+" $< > $@
|
||
|
endef
|
||
|
|
||
|
diff --git a/man/dmeventd.8_main b/man/dmeventd.8_main
|
||
|
index 75926bae5..7a780da7c 100644
|
||
|
--- a/man/dmeventd.8_main
|
||
|
+++ b/man/dmeventd.8_main
|
||
|
@@ -10,6 +10,8 @@ dmeventd \(em Device-mapper event daemon
|
||
|
.RB [ -d
|
||
|
.RB [ -d
|
||
|
.RB [ -d ]]]
|
||
|
+.RB [ -e
|
||
|
+.BR exit_on_path ]
|
||
|
.RB [ -f ]
|
||
|
.RB [ -h ]
|
||
|
.RB [ -i ]
|
||
|
@@ -37,6 +39,16 @@ debug messages sent to syslog.
|
||
|
Each extra d adds more debugging information.
|
||
|
.
|
||
|
.TP
|
||
|
+.B -e exit_on_path
|
||
|
+Specifies the file path whose presence is checked by the daemon when it
|
||
|
+receives a signal (SIGINT, SIGTERM) and allows to exit even if there are still
|
||
|
+monitored devices.
|
||
|
+This can help with system shutdown where devices
|
||
|
+have not been unmonitored properly.
|
||
|
+To disable this behavior set this to the empty string "".
|
||
|
+Default value is "\fI#DEFAULT_DMEVENTD_EXIT_ON_PATH#\fP".
|
||
|
+.
|
||
|
+.TP
|
||
|
.B -f
|
||
|
Don't fork, run in the foreground.
|
||
|
.
|
||
|
--
|
||
|
2.48.1
|
||
|
|