:: Re: [Dng] Readiness notification
Página superior
Eliminar este mensaje
Responder a este mensaje
Autor: Isaac Dunham
Fecha:  
A: Laurent Bercot
Cc: dng
Asunto: Re: [Dng] Readiness notification
On Sat, Jun 13, 2015 at 01:53:44AM +0200, Laurent Bercot wrote:
> On 12/06/2015 22:21, marcxdv@??? wrote:
> >The trick is for the daemon process to only background when
> >it is ready to service requests (ie its parent process exits
> >when the child is ready).
>
> This is bad design, for several reasons...
> The reasons why it's bad are mostly described here:
> http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/unix-daemon-design-mistakes-to-avoid.html
>
> Your solution enforces forking, i.e. auto-backgrounding, and
> prevents logging to stderr; in doing so, it prevents daemons from
> ever being used with a supervision framework. systemd may be able
> to supervise it, using cgroups, but that's about it, unless the
> admin is using foreground hacks.
>
> Moreover, the method you are using to transmit one bit of information,
> i.e. readiness of the service, is *the death of a process*. This
> is pretty heavy on the system; a simple write() does the job just
> as well, and hundreds of times faster.


I think that a program that must run in the background is broken.
Yet *prohibiting* auto-backgrounding imposes an even more heavy toll
on scripts where <process 1> requires <process 2> to be running and
ready: you *must* run a supervisor, or else run a lame-not-quite-a-
supervisor, just to do what would have been trivially done in a few
more lines of C.

While I haven't written the code yet, it strikes me that it should
be trivial to write something that can handle both styles of
notification, and maybe even share some of the code.
Essentially, part of the auto-background code becomes a trivial
not-quite-a-supervisor that exits as soon as it receives the same
notification that you use.
In the example, I'd want an option like "-S <fd>", where <fd>
is the fd that goes to the pipe the supervisor is listening to.

Pseudocode for this without proper error checking:
  int pipefds[2];
  pid_t pid = 0;
  parse options;
  if (supervised) {
    pipefds[0] = -1;
    pipefds[1] = supervisor_fd;
  } else if (background_option) {
    pipe(pipefds);
    pid = fork();
    if (pid < 0) {
      error_exit();
    } else if (pid > 0) {
      //close write end of pipe and watch read end till the pipe closes
    } else /* if (pid == 0) */ {
      //close read end of pipe
    }
  }
  // setup process
  if (supervised || background_option) {
    write(pipefds[1], "1", 1);
    close(pipefds[1]);
  }



Thanks,
Isaac Dunham