mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
dmeventd: fix dmeventd -R to work properly with systemd
Trying to restart dmeventd as a reload action is causing problems under systemd environment. The systemd loses track of new dmeventd this way. See also https://bugzilla.redhat.com/show_bug.cgi?id=1060134 for more info. We need to call dmeventd -R directly instead of "systemctl reload dm-event.service" that was used before (the reload is aimed at configuration reload anyway, not stateful restart of the daemon - we did this before just because there's no ExecRestart in systemd and there's only ExecStart and ExecStop with which we'd lose the state). Also, use ExecStart="dmeventd -f" to run dmeventd in foreground (and let's rely on systemd to daemonize it) and change the service type from "forking" to "simple".
This commit is contained in:
parent
36f9fadcb4
commit
8a8abc5ed9
@ -1823,6 +1823,59 @@ static void _daemonize(void)
|
||||
setsid();
|
||||
}
|
||||
|
||||
static int _reinstate_registrations(struct dm_event_fifos *fifos)
|
||||
{
|
||||
static const char _failed_parsing_msg[] = "Failed to parse existing event registration.\n";
|
||||
static const char *_delim = " ";
|
||||
struct dm_event_daemon_message msg = { 0 };
|
||||
char *endp, *dso_name, *dev_name, *mask, *timeout;
|
||||
unsigned long mask_value, timeout_value;
|
||||
int i, ret;
|
||||
|
||||
ret = daemon_talk(fifos, &msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0);
|
||||
dm_free(msg.data);
|
||||
msg.data = NULL;
|
||||
|
||||
if (ret) {
|
||||
fprintf(stderr, "Failed to communicate with new instance of dmeventd.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; _initial_registrations[i]; ++i) {
|
||||
if (!(strtok(_initial_registrations[i], _delim)) ||
|
||||
!(dso_name = strtok(NULL, _delim)) ||
|
||||
!(dev_name = strtok(NULL, _delim)) ||
|
||||
!(mask = strtok(NULL, _delim)) ||
|
||||
!(timeout = strtok(NULL, _delim))) {
|
||||
fprintf(stderr, _failed_parsing_msg);
|
||||
continue;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
mask_value = strtoul(mask, &endp, 10);
|
||||
if (errno || !endp || *endp) {
|
||||
fprintf(stderr, _failed_parsing_msg);
|
||||
continue;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
timeout_value = strtoul(timeout, &endp, 10);
|
||||
if (errno || !endp || *endp) {
|
||||
fprintf(stderr, _failed_parsing_msg);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (daemon_talk(fifos, &msg, DM_EVENT_CMD_REGISTER_FOR_EVENT,
|
||||
dso_name,
|
||||
dev_name,
|
||||
(enum dm_event_mask) mask_value,
|
||||
timeout_value))
|
||||
fprintf(stderr, "Failed to reinstate monitoring for device %s.\n", dev_name);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void restart(void)
|
||||
{
|
||||
struct dm_event_fifos fifos = {
|
||||
@ -1837,9 +1890,9 @@ static void restart(void)
|
||||
char *message;
|
||||
int length;
|
||||
int version;
|
||||
const char *e;
|
||||
|
||||
/* Get the list of registrations from the running daemon. */
|
||||
|
||||
if (!init_fifos(&fifos)) {
|
||||
fprintf(stderr, "WARNING: Could not initiate communication with existing dmeventd.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
@ -1891,18 +1944,54 @@ static void restart(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for daemon to die, detected by sending further DIE messages
|
||||
* until one fails.
|
||||
* If we're under systemd management, just send the initial
|
||||
* registrations to the fifo - this will instantiate new dmeventd.
|
||||
* If not under systemd management, continue with this process
|
||||
* to take over the old dmeventd.
|
||||
*/
|
||||
if (!(e = getenv(SD_ACTIVATION_ENV_VAR_NAME)) || strcmp(e, "1")) {
|
||||
/*
|
||||
* Non-systemd environment.
|
||||
* Wait for daemon to die, detected by sending further DIE messages
|
||||
* until one fails. This is really silly, but since nobody cleans up
|
||||
* the pidfile after SIGKILL is received in old dmeventd, we have to
|
||||
* do it this way.
|
||||
*/
|
||||
for (i = 0; i < 10; ++i) {
|
||||
if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_DIE, "-", "-", 0, 0))
|
||||
break; /* yep, it's dead probably */
|
||||
usleep(10);
|
||||
}
|
||||
fini_fifos(&fifos);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Systemd environment.
|
||||
* Wait for daemon to die, detected by checking the pidfile.
|
||||
* We can do this - systemd cleans up the pidfile automatically
|
||||
* for us even if we don't do that when SIGKILL is received in old dmeventd.
|
||||
*/
|
||||
for (i = 0; i < 10; ++i) {
|
||||
if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_DIE, "-", "-", 0, 0))
|
||||
break; /* yep, it's dead probably */
|
||||
if ((access(DMEVENTD_PIDFILE, F_OK) == -1) && (errno == ENOENT))
|
||||
break;
|
||||
usleep(10);
|
||||
}
|
||||
|
||||
/* Reopen fifos. */
|
||||
fini_fifos(&fifos);
|
||||
if (!init_fifos(&fifos)) {
|
||||
fprintf(stderr, "Could not initiate communication with new instance of dmeventd.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return;
|
||||
if (!_reinstate_registrations(&fifos)) {
|
||||
fprintf(stderr, "Failed to reinstate monitoring with new instance of dmeventd.\n");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
fini_fifos(&fifos);
|
||||
exit(EXIT_SUCCESS);
|
||||
bad:
|
||||
fini_fifos(&fifos);
|
||||
exit(EXIT_FAILURE);
|
||||
|
@ -7,9 +7,8 @@ Before=local-fs.target
|
||||
DefaultDependencies=no
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
ExecStart=@sbindir@/dmeventd
|
||||
ExecReload=@sbindir@/dmeventd -R
|
||||
Type=simple
|
||||
ExecStart=@sbindir@/dmeventd -f
|
||||
Environment=SD_ACTIVATION=1
|
||||
PIDFile=@DMEVENTD_PIDFILE@
|
||||
OOMScoreAdjust=-1000
|
||||
|
Loading…
Reference in New Issue
Block a user