qsd: Add --daemonize

To implement this, we reuse the existing daemonizing functions from the
system emulator, which mainly do the following:
- Fork off a child process, and set up a pipe between parent and child
- The parent process waits until the child sends a status byte over the
  pipe (0 means that the child was set up successfully; anything else
  (including errors or EOF) means that the child was not set up
  successfully), and then exits with an appropriate exit status
- The child process enters a new session (forking off again), changes
  the umask, and will ignore terminal signals from then on
- Once set-up is complete, the child will chdir to /, redirect all
  standard I/O streams to /dev/null, and tell the parent that set-up has
  been completed successfully

In contrast to qemu-nbd's --fork implementation, during the set up
phase, error messages are not piped through the parent process.
qemu-nbd mainly does this to detect errors, though (while os_daemonize()
has the child explicitly signal success after set up); because we do not
redirect stderr after forking, error messages continue to appear on
whatever the parent's stderr was (until set up is complete).

Signed-off-by: Hanna Reitz <hreitz@redhat.com>
Message-Id: <20220303164814.284974-4-hreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Hanna Reitz 2022-03-03 17:48:13 +01:00 committed by Kevin Wolf
parent 79d51d7317
commit 2525edd85f
2 changed files with 22 additions and 0 deletions

View File

@ -154,6 +154,13 @@ Standard options:
created but before accepting connections. The daemon has started successfully
when the pid file is written and clients may begin connecting.
.. option:: --daemonize
Daemonize the process. The parent process will exit once startup is complete
(i.e., after the pid file has been or would have been written) or failure
occurs. Its exit code reflects whether the child has started up successfully
or failed to do so.
Examples
--------
Launch the daemon with QMP monitor socket ``qmp.sock`` so clients can execute

View File

@ -93,6 +93,9 @@ static void help(void)
" --chardev <options> configure a character device backend\n"
" (see the qemu(1) man page for possible options)\n"
"\n"
" --daemonize daemonize the process, and have the parent exit\n"
" once startup is complete\n"
"\n"
" --export [type=]nbd,id=<id>,node-name=<node-name>[,name=<export-name>]\n"
" [,writable=on|off][,bitmap=<name>]\n"
" export the specified block node over NBD\n"
@ -144,6 +147,7 @@ QEMU_HELP_BOTTOM "\n",
enum {
OPTION_BLOCKDEV = 256,
OPTION_CHARDEV,
OPTION_DAEMONIZE,
OPTION_EXPORT,
OPTION_MONITOR,
OPTION_NBD_SERVER,
@ -200,6 +204,7 @@ static void process_options(int argc, char *argv[], bool pre_init_pass)
static const struct option long_options[] = {
{"blockdev", required_argument, NULL, OPTION_BLOCKDEV},
{"chardev", required_argument, NULL, OPTION_CHARDEV},
{"daemonize", no_argument, NULL, OPTION_DAEMONIZE},
{"export", required_argument, NULL, OPTION_EXPORT},
{"help", no_argument, NULL, 'h'},
{"monitor", required_argument, NULL, OPTION_MONITOR},
@ -225,6 +230,7 @@ static void process_options(int argc, char *argv[], bool pre_init_pass)
c == '?' ||
c == 'h' ||
c == 'V' ||
c == OPTION_DAEMONIZE ||
c == OPTION_PIDFILE;
/* Process every option only in its respective pass */
@ -277,6 +283,12 @@ static void process_options(int argc, char *argv[], bool pre_init_pass)
qemu_opts_del(opts);
break;
}
case OPTION_DAEMONIZE:
if (os_set_daemonize(true) < 0) {
error_report("--daemonize not supported in this build");
exit(EXIT_FAILURE);
}
break;
case OPTION_EXPORT:
{
Visitor *v;
@ -367,6 +379,8 @@ int main(int argc, char *argv[])
process_options(argc, argv, true);
os_daemonize();
module_call_init(MODULE_INIT_QOM);
module_call_init(MODULE_INIT_TRACE);
qemu_add_opts(&qemu_trace_opts);
@ -389,6 +403,7 @@ int main(int argc, char *argv[])
* it.
*/
pid_file_init();
os_setup_post();
while (!exit_requested) {
main_loop_wait(false);