lvm2/0137-dmeventd-implement-exit_on-file-check.patch

197 lines
6.5 KiB
Diff
Raw Permalink Normal View History

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