http://www.perlmonks.org?node_id=1196881

markoh has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I have written a daemon with the help of this post Re: Writing a Perl Daemon. The daemon more or less follows the structure shown there. The daemon is installed in CentOS 7 within systemd environment. It is declared there as forking type of daemon with a PID file and everything that goes with it.

Now I have a problem with it. The daemon sends data to two servers (for redundancy purposes) every two seconds. When both remote servers are up, everything is fine. However, when one of the servers is down, there are problems. The procedure waits for disconnected server to respond and at that time the data are not sent to the connected server too.

I need the daemon to have two child processes. Each one would send the data to one of the servers. In that case difficulties with one server would not cause problems with another one. I am not sure if Proc::Daemon and Proc::PID::File support more than one child process.

I tried something like this:

foreach my $server (@servers) { $i++; # # fork and background process # our $ME = $0; $ME =~ s|.*/||; our $PIDFILE = $PIDDIR . "/$ME.pid" . $i; my $pid = 0; $daemon{$server} = Proc::Daemon->new ( pid_file => $PIDFILE, work_dir => cwd () ); $pid = $daemon{$server}->Init (); if ($pid == 0) { # do the child stuff } }

When I run this daemon it creates children processes and more PID files. However, when I try to kill them, it is not so straightforward, because some a new child appears and I have to kill it too. I think I could resolve this issue, but there are more.

Since I use systemd where I have to specify PIDFile, I am also not sure if it is supported to have more PID files. I guess the right way would be to put all children PIDs into one PID file. Until now I was only testing this multiple children version with running the daemon manually. The strange behaviour with popping up children after killing the original ones stopped me from going further. I did not try to do it with systemd yet.

Where can I find some examples how to make a PERL daemon with more child processes? Since I use Proc::Daemon, Proc::PID::File, I would prefer to make it work with these libraries. I hope it can be done with them. Otherwise, I have to change quite a lot.

Replies are listed 'Best First'.
Re: Multiple forks with Proc::Daemon
by duelafn (Parson) on Aug 07, 2017 at 12:31 UTC

    No need for PID files if you don't daemonize the main process - systemd works best if the process doesn't daemonize. Systemd should be able to manage all children just fine and all you should need is a simple fork:

    my @children; foreach my $server (@servers) { my $child = fork; die "Fork error" unless defined($child); if ($child) { push @children, $child; } else { do_stuff($server); } } waitpid($_) for @children;

    The waitpid line will cause the main process to wait for all children before exiting (this is what systemd will use to know if any tasks are still running). You should be able to kill all remaining (stuck) processes using systemctl stop my-service (or if you want just a periodic run, periodically call systemctl restart my-service).

    Good Day,
        Dean

Re: Multiple forks with Proc::Daemon
by markoh (Novice) on Aug 07, 2017 at 08:41 UTC
    For a quick fix I have found a workaround. I will create two daemons each with separate configuration for now.
      When you finish your workaround/quick-fix, please post it here. TIA!

        I have only made a copy of the original daemon as suggested here https://access.redhat.com/solutions/1166283. Now there are two daemons with two sets of configuration and even log files. One is configured to connect to one server and the second one is configured to connect to the second server. The functionality to connect to more than one server within a daemon is not used.

        For writing a daemon, I have followed this template Re: Writing a Perl Daemon.