提交 fc5925f1 编写于 作者: R Rafael Fonseca 提交者: Michal Privoznik

util: introduce shared daemon startup code

Several daemons have similar code around general daemon startup code.
Let's move it into a file and share it among them.
Signed-off-by: NRafael Fonseca <r4f4rfs@gmail.com>
Signed-off-by: NMichal Privoznik <mprivozn@redhat.com>
Reviewed-by: NMichal Privoznik <mprivozn@redhat.com>
上级 769ff77c
......@@ -2016,7 +2016,7 @@ exclude_file_name_regexp--sc_prohibit_close = \
exclude_file_name_regexp--sc_prohibit_empty_lines_at_EOF = \
(^tests/(virhostcpu|virpcitest)data/|docs/js/.*\.js|docs/fonts/.*\.woff|\.diff|tests/virconfdata/no-newline\.conf$$)
_src2=src/(util/vircommand|libvirt|lxc/lxc_controller|locking/lock_daemon|logging/log_daemon|remote/remote_daemon)
_src2=src/(util/(vircommand|virdaemon)|libvirt|lxc/lxc_controller|locking/lock_daemon|logging/log_daemon|remote/remote_daemon)
exclude_file_name_regexp--sc_prohibit_fork_wrappers = \
(^($(_src2)|tests/testutils)\.c$$)
......
......@@ -236,6 +236,7 @@
@SRCDIR@/src/util/vircommand.c
@SRCDIR@/src/util/virconf.c
@SRCDIR@/src/util/vircrypto.c
@SRCDIR@/src/util/virdaemon.c
@SRCDIR@/src/util/virdbus.c
@SRCDIR@/src/util/virdnsmasq.c
@SRCDIR@/src/util/virerror.c
......
......@@ -1906,6 +1906,12 @@ virCryptoHashString;
virCryptoHaveCipher;
# util/virdaemon.h
virDaemonForkIntoBackground;
virDaemonSetupLogging;
virDaemonUnixSocketPaths;
# util/virdbus.h
virDBusCallMethod;
virDBusCloseSystemBus;
......
......@@ -42,6 +42,8 @@ UTIL_SOURCES = \
util/virconf.h \
util/vircrypto.c \
util/vircrypto.h \
util/virdaemon.c \
util/virdaemon.h \
util/virdbus.c \
util/virdbus.h \
util/virdbuspriv.h \
......
/*
* virdaemon.c: shared daemon setup code
*
* Copyright (C) 2020 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; If not, see
* <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdbool.h>
#include "virdaemon.h"
#include "virutil.h"
#include "virfile.h"
#include "virlog.h"
#include "viralloc.h"
#include "configmake.h"
int
virDaemonForkIntoBackground(const char *argv0)
{
int statuspipe[2];
if (virPipeQuiet(statuspipe) < 0)
return -1;
pid_t pid = fork();
switch (pid) {
case 0:
{
/* intermediate child */
int stdinfd = -1;
int stdoutfd = -1;
int nextpid;
VIR_FORCE_CLOSE(statuspipe[0]);
if ((stdinfd = open("/dev/null", O_RDONLY)) < 0)
goto cleanup;
if ((stdoutfd = open("/dev/null", O_WRONLY)) < 0)
goto cleanup;
if (dup2(stdinfd, STDIN_FILENO) != STDIN_FILENO)
goto cleanup;
if (dup2(stdoutfd, STDOUT_FILENO) != STDOUT_FILENO)
goto cleanup;
if (dup2(stdoutfd, STDERR_FILENO) != STDERR_FILENO)
goto cleanup;
if (VIR_CLOSE(stdinfd) < 0)
goto cleanup;
if (VIR_CLOSE(stdoutfd) < 0)
goto cleanup;
if (setsid() < 0)
goto cleanup;
nextpid = fork();
switch (nextpid) {
case 0: /* grandchild */
return statuspipe[1];
case -1: /* error */
goto cleanup;
default: /* intermediate child succeeded */
_exit(EXIT_SUCCESS);
}
cleanup:
VIR_FORCE_CLOSE(stdoutfd);
VIR_FORCE_CLOSE(stdinfd);
VIR_FORCE_CLOSE(statuspipe[1]);
_exit(EXIT_FAILURE);
}
case -1: /* error in parent */
goto error;
default:
{
/* parent */
int got, exitstatus = 0;
int ret;
char status;
VIR_FORCE_CLOSE(statuspipe[1]);
/* We wait to make sure the first child forked successfully */
if ((got = waitpid(pid, &exitstatus, 0)) < 0 ||
got != pid ||
exitstatus != 0) {
goto error;
}
/* If we got here, then the grandchild was spawned, so we
* must exit. Block until the second child initializes
* successfully */
ret = saferead(statuspipe[0], &status, 1);
VIR_FORCE_CLOSE(statuspipe[0]);
if (ret != 1) {
fprintf(stderr,
_("%s: error: unable to determine if daemon is "
"running: %s\n"), argv0,
g_strerror(errno));
exit(EXIT_FAILURE);
} else if (status != 0) {
fprintf(stderr,
_("%s: error: %s. Check /var/log/messages or run without "
"--daemon for more info.\n"), argv0,
virDaemonErrTypeToString(status));
exit(EXIT_FAILURE);
}
_exit(EXIT_SUCCESS);
}
}
error:
VIR_FORCE_CLOSE(statuspipe[0]);
VIR_FORCE_CLOSE(statuspipe[1]);
return -1;
}
/*
* Set up the logging environment
* By default if daemonized all errors go to the logfile libvirtd.log,
* but if verbose or error debugging is asked for then also output
* informational and debug messages. Default size if 64 kB.
*/
void
virDaemonSetupLogging(const char *daemon_name,
unsigned int log_level,
char *log_filters,
char *log_outputs,
bool privileged,
bool verbose,
bool godaemon)
{
virLogReset();
/*
* Libvirtd's order of precedence is:
* cmdline > environment > config
*
* Given the precedence, we must process the variables in the opposite
* order, each one overriding the previous.
*/
if (log_level != 0)
virLogSetDefaultPriority(log_level);
/* In case the config is empty, both filters and outputs will become empty,
* however we can't start with empty outputs, thus we'll need to define and
* setup a default one.
*/
ignore_value(virLogSetFilters(log_filters));
ignore_value(virLogSetOutputs(log_outputs));
/* If there are some environment variables defined, use those instead */
virLogSetFromEnv();
/*
* Command line override for --verbose
*/
if ((verbose) && (virLogGetDefaultPriority() > VIR_LOG_INFO))
virLogSetDefaultPriority(VIR_LOG_INFO);
/* Define the default output. This is only applied if there was no setting
* from either the config or the environment.
*/
virLogSetDefaultOutput(daemon_name, godaemon, privileged);
if (virLogGetNbOutputs() == 0)
virLogSetOutputs(virLogGetDefaultOutput());
}
int
virDaemonUnixSocketPaths(const char *sock_prefix,
bool privileged,
char *unix_sock_dir,
char **sockfile,
char **rosockfile,
char **admsockfile)
{
int ret = -1;
char *rundir = NULL;
if (unix_sock_dir) {
if (sockfile)
*sockfile = g_strdup_printf("%s/%s-sock", unix_sock_dir, sock_prefix);
if (privileged) {
if (rosockfile)
*rosockfile = g_strdup_printf("%s/%s-sock-ro",
unix_sock_dir, sock_prefix);
if (admsockfile)
*admsockfile = g_strdup_printf("%s/%s-admin-sock",
unix_sock_dir, sock_prefix);
}
} else {
if (privileged) {
if (sockfile)
*sockfile = g_strdup_printf("%s/libvirt/%s-sock",
RUNSTATEDIR, sock_prefix);
if (rosockfile)
*rosockfile = g_strdup_printf("%s/libvirt/%s-sock-ro",
RUNSTATEDIR, sock_prefix);
if (admsockfile)
*admsockfile = g_strdup_printf("%s/libvirt/%s-admin-sock",
RUNSTATEDIR, sock_prefix);
} else {
mode_t old_umask;
rundir = virGetUserRuntimeDirectory();
old_umask = umask(077);
if (virFileMakePath(rundir) < 0) {
umask(old_umask);
goto cleanup;
}
umask(old_umask);
if (sockfile)
*sockfile = g_strdup_printf("%s/%s-sock", rundir, sock_prefix);
if (admsockfile)
*admsockfile = g_strdup_printf("%s/%s-admin-sock", rundir, sock_prefix);
}
}
ret = 0;
cleanup:
VIR_FREE(rundir);
return ret;
}
/*
* virdaemon.h: shared daemon setup code
*
* Copyright (C) 2020 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; If not, see
* <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "virenum.h"
enum {
VIR_DAEMON_ERR_NONE = 0,
VIR_DAEMON_ERR_PIDFILE,
VIR_DAEMON_ERR_RUNDIR,
VIR_DAEMON_ERR_INIT,
VIR_DAEMON_ERR_SIGNAL,
VIR_DAEMON_ERR_PRIVS,
VIR_DAEMON_ERR_NETWORK,
VIR_DAEMON_ERR_CONFIG,
VIR_DAEMON_ERR_HOOKS,
VIR_DAEMON_ERR_REEXEC,
VIR_DAEMON_ERR_AUDIT,
VIR_DAEMON_ERR_DRIVER,
VIR_DAEMON_ERR_LAST
};
VIR_ENUM_DECL(virDaemonErr);
VIR_ENUM_IMPL(virDaemonErr,
VIR_DAEMON_ERR_LAST,
"Initialization successful",
"Unable to obtain pidfile",
"Unable to create rundir",
"Unable to initialize libvirt",
"Unable to setup signal handlers",
"Unable to drop privileges",
"Unable to initialize network sockets",
"Unable to load configuration file",
"Unable to look for hook scripts",
"Unable to re-execute daemon",
"Unable to initialize audit system",
"Unable to initialize driver",
);
int virDaemonForkIntoBackground(const char *argv0);
void virDaemonSetupLogging(const char *daemon_name,
unsigned int log_level,
char *log_filters,
char *log_outputs,
bool privileged,
bool verbose,
bool godaemon);
int virDaemonUnixSocketPaths(const char *sock_prefix,
bool privileged,
char *unix_sock_dir,
char **sockfile,
char **rosockfile,
char **adminSockfile);
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册