CTKlib

 view release on metacpan or  search on metacpan

lib/CTK/Daemon.pm  view on Meta::CPAN

}
sub ctk { goto &get_ctk }

#
# Methods for overwriting in user class
#

# Please overwrite in subclass
#  this is called at startup - before forking
sub init {
    my $self = shift;
    return 1;
}
# Please overwrite in subclass
#  this is called at cleanup - after processing each forks
sub down {
    my $self = shift;
    return 1;
}
# Please overwrite in subclass
#  this is called at startup of each forks
sub run {
    my $self = shift;
    return 1;
}
# Please overwrite in subclass
#  this is called at before running of each forks
sub reload {
    my $self = shift;
    return 1;
}
# Please overwrite in subclass
#  this is called at before exit from main fork
sub cleanup {
    my $self = shift;
    return 1;
}

#
# LSB methods
#

sub start {
    my $self = shift;
    my $logger = $self->logger;

    # Load GID and UID
    my ($uid, $gid);
    if (my $uidstr = $self->{uid}) {
        $uid = getpwnam($uidstr) || croak "getpwnam failed - $!\n";
    }
    if (my $gidstr = $self->{gid}) {
        $gid = getgrnam($gidstr) || croak "getgrnam failed - $!\n";
    }

    # PidFile prepare
    if (defined($uid) or defined($gid)) {
        my $pidfile = $self->{pidfile};
        unless (-e $pidfile) {
            CTK::Util::fsave($pidfile, "0\n");
            chown($uid, $gid, $pidfile) if -e $pidfile;
        }
    }

    # Set GID and UID
    if (defined($gid)) {
        POSIX::setgid($gid) || croak "setgid $gid failed - $!\n";
        $) = "$gid $gid"; # this calls setgroups
        croak "detected strange gid\n" if !($( eq "$gid $gid" && $) eq "$gid $gid"); # just to be sure
    }
    if (defined($uid)) {
        POSIX::setuid($uid) || croak "setuid $uid failed - $!\n";
        croak "detected strange uid\n" if !($< == $uid && $> == $uid); # just to be sure
    }

    my $save_pid = $$;
    #say "PID> $$";
    #say "INITPID> ".$self->{initpid};
    my $pidf = $self->{initpidf};

    # Run init handler
    $self->init() or return 1; # error level (exit code)

    # Start master process
    my $pid = myfork();
    if ($pid) {
        print("Started\n");
        if ($self->{debug}) {
            $logger->log_debug("Master process (pid=%d) successfully started", $pid) if $logger;
        } else {
            $logger->log_debug("Started") if $logger;
        }
    }
    $self->logger_close;

    if ( defined($pid) && $pid == 0 ) { # The master child runs here.
        $pidf->pid(isostype('Windows') ? $save_pid : $$);
        $self->{masterpid} = $pidf->pid;
        $pidf->write;

        # Detach the child from the terminal (no controlling tty), make it the
        # session-leader and the process-group-leader of a new process group.
        unless ($DEV_DEBUG || isostype('Windows')) {
            die "Can't detach from controlling terminal" if POSIX::setsid() < 0;
        }

        # Catching the signals
        $SIG{$_} = $sigproxy for keys %LOCAL_SIG;
        $self->{sigs} = {%LOCAL_SIG};
        #say Dumper($self);


        # Second fork. See Proc::Daemon
        my (@pids, %pidh);
        for (my $j = 1; $j <= $self->{forkers}; $j++) {
            my $cpid = myfork();
            if ( defined($cpid) && $cpid == 0 ) { # Here the second child is running.
                # Close all file handles and descriptors the user does not want to preserve.
                my $devnull = File::Spec->devnull;
                unless ($DEV_DEBUG || ($self->{debug} && isostype('Windows'))) {
                    open( STDIN, "<", $devnull ) or die "Failed to open STDIN to $devnull: $!";;



( run in 1.637 second using v1.01-cache-2.11-cpan-71847e10f99 )