[libvirt] [PATCH 05/14] Introduce basic infrastructure for virtlockd daemon
Daniel P. Berrange
berrange at redhat.com
Thu Dec 13 12:25:15 UTC 2012
On Wed, Dec 12, 2012 at 07:14:20PM +0100, Michal Privoznik wrote:
> On 11.12.2012 21:41, Daniel P. Berrange wrote:
> > +static int
> > +virLockDaemonForkIntoBackground(const char *argv0)
> > +{
> > + int statuspipe[2];
> > + if (pipe(statuspipe) < 0)
> > + return -1;
> > +
> > + pid_t pid = fork();
> > + switch (pid) {
> > + case 0:
> > + {
> > + 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:
> > + return statuspipe[1];
> > + case -1:
> > + return -1;
> > + default:
> > + _exit(0);
> > + }
> > +
> > + cleanup:
> > + VIR_FORCE_CLOSE(stdoutfd);
> > + VIR_FORCE_CLOSE(stdinfd);
> > + return -1;
> > +
> > + }
> > +
> > + case -1:
> > + return -1;
> > +
> > + default:
> > + {
> > + 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) {
> > + return -1;
> > + }
> > +
> > + /* Now block until the second child initializes successfully */
> > + again:
> > + ret = read(statuspipe[0], &status, 1);
> > + if (ret == -1 && errno == EINTR)
> > + goto again;
> > +
> > + if (ret == 1 && status != 0) {
> > + fprintf(stderr,
> > + _("%s: error: %s. Check /var/log/messages or run without "
> > + "--daemon for more info.\n"), argv0,
> > + virDaemonErrTypeToString(status));
> > + }
> > + _exit(ret == 1 && status == 0 ? 0 : 1);
> > + }
> > + }
> > +}
>
> This is basically a copy-paste of daemonForkIntoBackground(). I wonder
> if we can use (modified) version of it instead of this.
Yep, it would be nice to share more code between the daemons in the
future, but I didn't want to tackle that right now.
> > +/*
> > + * 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.
> > + */
> > +static int
> > +virLockDaemonSetupLogging(virLockDaemonConfigPtr config,
> > + bool privileged,
> > + bool verbose,
> > + bool godaemon)
> > +{
> > + virLogReset();
> > +
> > + /*
> > + * Libvirtd's order of precedence is:
> > + * cmdline > environment > config
> > + *
> > + * In order to achieve this, we must process configuration in
> > + * different order for the log level versus the filters and
> > + * outputs. Because filters and outputs append, we have to look at
> > + * the environment first and then only check the config file if
> > + * there was no result from the environment. The default output is
> > + * then applied only if there was no setting from either of the
> > + * first two. Because we don't have a way to determine if the log
> > + * level has been set, we must process variables in the opposite
> > + * order, each one overriding the previous.
> > + */
> > + if (config->log_level != 0)
> > + virLogSetDefaultPriority(config->log_level);
> > +
> > + virLogSetFromEnv();
> > +
> > + virLogSetBufferSize(config->log_buffer_size);
> > +
> > + if (virLogGetNbFilters() == 0)
> > + virLogParseFilters(config->log_filters);
> > +
> > + if (virLogGetNbOutputs() == 0)
> > + virLogParseOutputs(config->log_outputs);
> > +
> > + /*
> > + * If no defined outputs, and either running
> > + * as daemon or not on a tty, then first try
> > + * to direct it to the systemd journal
> > + * (if it exists)....
> > + */
> > + if (virLogGetNbOutputs() == 0 &&
> > + (godaemon || !isatty(STDIN_FILENO))) {
> > + char *tmp;
> > + if (access("/run/systemd/journal/socket", W_OK) >= 0) {
> > + if (virAsprintf(&tmp, "%d:journald", virLogGetDefaultPriority()) < 0)
> > + goto no_memory;
> > + virLogParseOutputs(tmp);
> > + VIR_FREE(tmp);
> > + }
> > + }
> > +
> > + /*
> > + * otherwise direct to libvirtd.log when running
> > + * as daemon. Otherwise the default output is stderr.
> > + */
> > + if (virLogGetNbOutputs() == 0) {
> > + char *tmp = NULL;
> > +
> > + if (godaemon) {
> > + if (privileged) {
> > + if (virAsprintf(&tmp, "%d:file:%s/log/libvirt/virtlockd.log",
> > + virLogGetDefaultPriority(),
> > + LOCALSTATEDIR) == -1)
> > + goto no_memory;
> > + } else {
> > + char *logdir = virGetUserCacheDirectory();
> > + mode_t old_umask;
> > +
> > + if (!logdir)
> > + goto error;
> > +
> > + old_umask = umask(077);
> > + if (virFileMakePath(logdir) < 0) {
> > + umask(old_umask);
> > + goto error;
> > + }
> > + umask(old_umask);
> > +
> > + if (virAsprintf(&tmp, "%d:file:%s/virtlockd.log",
> > + virLogGetDefaultPriority(), logdir) == -1) {
> > + VIR_FREE(logdir);
> > + goto no_memory;
> > + }
> > + VIR_FREE(logdir);
> > + }
> > + } else {
> > + if (virAsprintf(&tmp, "%d:stderr", virLogGetDefaultPriority()) < 0)
> > + goto no_memory;
> > + }
> > + virLogParseOutputs(tmp);
> > + VIR_FREE(tmp);
> > + }
> > +
> > + /*
> > + * Command line override for --verbose
> > + */
> > + if ((verbose) && (virLogGetDefaultPriority() > VIR_LOG_INFO))
> > + virLogSetDefaultPriority(VIR_LOG_INFO);
> > +
> > + return 0;
> > +
> > +no_memory:
> > + virReportOOMError();
> > +error:
> > + return -1;
> > +}
>
> Same here. This one is even closer to daemonSetupLogging()
Yep, as above.
> > +#define MAX_LISTEN 5
> > +int main(int argc, char **argv) {
> > + char *remote_config_file = NULL;
> > + int statuswrite = -1;
> > + int ret = 1;
> > + int verbose = 0;
> > + int godaemon = 0;
> > + int timeout = 0;
>
> timeout seems dummy to me.
Yep, it is not required.
> ACK if you either remove it or (more likely) implement it.
Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
More information about the libvir-list
mailing list