]> sourceware.org Git - lvm2.git/commitdiff
dmeventd: implement exit_on file check
authorZdenek Kabelac <zkabelac@redhat.com>
Mon, 25 Sep 2023 11:07:00 +0000 (13:07 +0200)
committerZdenek Kabelac <zkabelac@redhat.com>
Mon, 25 Sep 2023 23:23:00 +0000 (01:23 +0200)
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).

daemons/dmeventd/dmeventd.c
make.tmpl.in
man/Makefile.in
man/dmeventd.8_main

index d38f9439dff3ff738a34b6a4d9069b2ba6dd2074..bf9976ed15654b7dbcd05ef78d95bab386aee1f7 100644 (file)
@@ -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;
        }
@@ -2242,8 +2249,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"
@@ -2266,7 +2274,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);
@@ -2279,6 +2287,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;
@@ -2291,6 +2306,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;
                }
        }
 
@@ -2381,15 +2399,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();
        }
index fcb62f78a8cc4f837b0f5ee0009d6bc6e6075a16..52903000d718233d291c2d13b43306fb68a27bd6 100644 (file)
@@ -167,6 +167,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@
 
 #----------------------------------------------------------------------
 # From http://blog.melski.net/tag/debugging-makefiles/
index 8488d309f97d0ed5f382050f9622a874d1e45089..148a4e0d388413f2285a229877ffbe04ce511c32 100644 (file)
@@ -180,6 +180,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
 
index 75926bae5bad0af65e55c94ed2a53218c31e0d09..7a780da7c75564feabac648ad5fa6243839b3b3e 100644 (file)
@@ -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.
 .
This page took 0.042354 seconds and 5 git commands to generate.