qemu-storage-daemon: add --pidfile option

Daemons often have a --pidfile option where the pid is written to a file
so that scripts can stop the daemon by sending a signal.

The pid file also acts as a lock to prevent multiple instances of the
daemon from launching for a given pid file.

QEMU, qemu-nbd, qemu-ga, virtiofsd, and qemu-pr-helper all support the
--pidfile option. Add it to qemu-storage-daemon too.

Reported-by: Richard W.M. Jones <rjones@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-Id: <20210302142746.170535-1-stefanha@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2021-03-02 14:27:46 +00:00 committed by Kevin Wolf
parent 501a4b3681
commit 03d2b412aa
2 changed files with 50 additions and 0 deletions

View File

@ -118,6 +118,20 @@ Standard options:
List object properties with ``<type>,help``. See the :manpage:`qemu(1)` List object properties with ``<type>,help``. See the :manpage:`qemu(1)`
manual page for a description of the object properties. manual page for a description of the object properties.
.. option:: --pidfile PATH
is the path to a file where the daemon writes its pid. This allows scripts to
stop the daemon by sending a signal::
$ kill -SIGTERM $(<path/to/qsd.pid)
A file lock is applied to the file so only one instance of the daemon can run
with a given pid file path. The daemon unlinks its pid file when terminating.
The pid file is written after chardevs, exports, and NBD servers have been
created but before accepting connections. The daemon has started successfully
when the pid file is written and clients may begin connecting.
Examples Examples
-------- --------
Launch the daemon with QMP monitor socket ``qmp.sock`` so clients can execute Launch the daemon with QMP monitor socket ``qmp.sock`` so clients can execute

View File

@ -59,6 +59,7 @@
#include "sysemu/runstate.h" #include "sysemu/runstate.h"
#include "trace/control.h" #include "trace/control.h"
static const char *pid_file;
static volatile bool exit_requested = false; static volatile bool exit_requested = false;
void qemu_system_killed(int signal, pid_t pid) void qemu_system_killed(int signal, pid_t pid)
@ -115,6 +116,8 @@ static void help(void)
" See the qemu(1) man page for documentation of the\n" " See the qemu(1) man page for documentation of the\n"
" objects that can be added.\n" " objects that can be added.\n"
"\n" "\n"
" --pidfile <path> write process ID to a file after startup\n"
"\n"
QEMU_HELP_BOTTOM "\n", QEMU_HELP_BOTTOM "\n",
error_get_progname()); error_get_progname());
} }
@ -126,6 +129,7 @@ enum {
OPTION_MONITOR, OPTION_MONITOR,
OPTION_NBD_SERVER, OPTION_NBD_SERVER,
OPTION_OBJECT, OPTION_OBJECT,
OPTION_PIDFILE,
}; };
extern QemuOptsList qemu_chardev_opts; extern QemuOptsList qemu_chardev_opts;
@ -178,6 +182,7 @@ static void process_options(int argc, char *argv[])
{"monitor", required_argument, NULL, OPTION_MONITOR}, {"monitor", required_argument, NULL, OPTION_MONITOR},
{"nbd-server", required_argument, NULL, OPTION_NBD_SERVER}, {"nbd-server", required_argument, NULL, OPTION_NBD_SERVER},
{"object", required_argument, NULL, OPTION_OBJECT}, {"object", required_argument, NULL, OPTION_OBJECT},
{"pidfile", required_argument, NULL, OPTION_PIDFILE},
{"trace", required_argument, NULL, 'T'}, {"trace", required_argument, NULL, 'T'},
{"version", no_argument, NULL, 'V'}, {"version", no_argument, NULL, 'V'},
{0, 0, 0, 0} {0, 0, 0, 0}
@ -289,6 +294,9 @@ static void process_options(int argc, char *argv[])
qobject_unref(args); qobject_unref(args);
break; break;
} }
case OPTION_PIDFILE:
pid_file = optarg;
break;
case 1: case 1:
error_report("Unexpected argument"); error_report("Unexpected argument");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -299,6 +307,27 @@ static void process_options(int argc, char *argv[])
loc_set_none(); loc_set_none();
} }
static void pid_file_cleanup(void)
{
unlink(pid_file);
}
static void pid_file_init(void)
{
Error *err = NULL;
if (!pid_file) {
return;
}
if (!qemu_write_pidfile(pid_file, &err)) {
error_reportf_err(err, "cannot create PID file: ");
exit(EXIT_FAILURE);
}
atexit(pid_file_cleanup);
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
#ifdef CONFIG_POSIX #ifdef CONFIG_POSIX
@ -326,6 +355,13 @@ int main(int argc, char *argv[])
qemu_init_main_loop(&error_fatal); qemu_init_main_loop(&error_fatal);
process_options(argc, argv); process_options(argc, argv);
/*
* Write the pid file after creating chardevs, exports, and NBD servers but
* before accepting connections. This ordering is documented. Do not change
* it.
*/
pid_file_init();
while (!exit_requested) { while (!exit_requested) {
main_loop_wait(false); main_loop_wait(false);
} }