:: Re: [DNG] Detailed technical treati…
Top Page
Delete this message
Reply to this message
Author: Rainer Weikusat
Date:  
To: dng
Subject: Re: [DNG] Detailed technical treatise of systemd
Arnt Gulbrandsen <arnt@???> writes:
> Steve Litt writes:
>> I'd like to discuss this. Now, after a year of thought, I still see no
>> benefit to "starting servers in parallel" except for boot time.
>
> Because you're thinking of the happy path.
>
> Suppose you have a few dozen servers on three continents, providing a
> user-facing service, using something like zk or etcd to coordinate the
> servers.
>
> Suppose further that something on the servers does five DNS lookups at
> startup. On the happy path that takes 5*0.008=0.04 seconds and who
> cares, but the worst case is in minutes. Say five 90-second
> timeouts.


A simple solution to this problem would be: Ensure that 'servers' don't
daemonize themselves but start them all with the help of a tool
performing this. Since all 'server code' will then be executed from the
forked process, startup can immediately move on, effectively
parallellized without any additional effort.

NB: This is restricted to the task itself and it doesn't bother with the
'ensure no controlling terminal can ever be acquired again' part of the
procedure the FatDoorstop wrecking crew ripped out of APUE in order to
help marketing their "engineering marvel".

----------
/*
Daemonize a process. Unless -n is passed as first argument,
all open files will be closed and descriptors 0, 1 and 2
associated with /dev/null prior to executing the actual
command.

Copyright (C) Rainer Weikusat 2015

Free to use according to the conditions set out in GPLv2
or any later version.

      $Id: daemon.c,v 1.4 2015/11/07 16:44:11 rw Exp $
*/


/* includes */
#include <errno.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdlib.h>
#include <syslog.h>
#include <unistd.h>

/*  macros */
#define FDS    "/proc/self/fd"


/* variables */
static int setup_fds = 1;

/*  main */
static int die(char const *sysc, char const *fnc)
{
    syslog(LOG_ERR, "%s: %s: %m(%d)", sysc, fnc, errno);
    exit(1);
}


static char **parse_args(char **argv)
{
    char *s;


    s = *++argv;
    if (*s == '-' && s[1] && !s[2])
    switch (s[1]) {
    case 'n':
        setup_fds = 0;

    
    case '-':
        ++argv;
    }


    return argv;
}


static void close_open_fds(void)
{
    struct dirent *d_ent;
    char *endptr;
    DIR *dir;
    int dir_fd, fd;


    dir = opendir(FDS);
    if (!dir) die(__func__, "opendir");
    dir_fd = dirfd(dir);


    while ((d_ent = readdir(dir))) {
    fd = strtoul(d_ent->d_name, &endptr, 10);
    if (fd != dir_fd && !*endptr) close(fd);
    }


    closedir(dir);
}


static void do_fd_setup(void)
{
    close_open_fds();


    open("/dev/null", O_RDWR, 0);
    dup(0);
    dup(0);
}


int main(int argc, char **argv)
{
    char **cmdv;


    /* stop reinventing logging systems */
    openlog("daemon", LOG_PID | LOG_PERROR, LOG_DAEMON);


    if (argc == 1) {
    syslog(LOG_NOTICE, "Usage: daemon [-n] <cmd> <arg>*");
    exit(1);
    }


    cmdv = parse_args(argv);
    switch (fork()) {
    case -1:
    die(__func__, "fork");


    case 0:
    break;


    default:
    _exit(0);
    }


    setsid();
    if (setup_fds) do_fd_setup();
    execvp(*cmdv, cmdv);


    die(__func__, "execvp");
    return 0;
}