1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

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).
This commit is contained in:
Zdenek Kabelac 2023-09-25 13:07:00 +02:00
parent 3da18a06d8
commit a9d7a9d128
4 changed files with 58 additions and 13 deletions

View 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();
}

View 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/

View 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

View 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.
.