Fix Run Now backup process getting killed on CGI exit

The forked child stayed in the CGI's process group and got killed
when Apache cleaned up the CGI process. Now uses double-fork with
POSIX::setsid() to fully daemonize the backup process.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
shuki
2026-03-04 04:53:18 +02:00
parent f881a80557
commit 749881dd5d

View File

@@ -8,6 +8,7 @@ use lib '/usr/local/cpanel/whostmgr/docroot/cgi/gniza-whm/lib';
use Whostmgr::HTMLInterface (); use Whostmgr::HTMLInterface ();
use Cpanel::Form (); use Cpanel::Form ();
use File::Copy (); use File::Copy ();
use POSIX ();
use GnizaWHM::Config; use GnizaWHM::Config;
use GnizaWHM::Validator; use GnizaWHM::Validator;
use GnizaWHM::Cron; use GnizaWHM::Cron;
@@ -376,7 +377,7 @@ sub handle_run_now {
my $log_file = "/var/log/gniza/cron-${name}.log"; my $log_file = "/var/log/gniza/cron-${name}.log";
# Fork to background # Double-fork to fully detach from CGI process group
my $pid = fork(); my $pid = fork();
if (!defined $pid) { if (!defined $pid) {
GnizaWHM::UI::set_flash('error', "Failed to fork backup process: $!"); GnizaWHM::UI::set_flash('error', "Failed to fork backup process: $!");
@@ -386,17 +387,24 @@ sub handle_run_now {
} }
if ($pid == 0) { if ($pid == 0) {
# Child: detach and exec # First child: new session, then fork again
POSIX::setsid();
my $pid2 = fork();
exit 0 if $pid2; # first child exits immediately
# Grandchild: fully detached daemon
close STDIN; close STDIN;
open STDIN, '<', '/dev/null';
close STDOUT; close STDOUT;
close STDERR;
open STDOUT, '>>', $log_file; open STDOUT, '>>', $log_file;
close STDERR;
open STDERR, '>&', \*STDOUT; open STDERR, '>&', \*STDOUT;
exec @cmd; exec @cmd;
exit 1; exit 1;
} }
# Parent: don't wait, redirect immediately waitpid($pid, 0); # Reap first child (exits immediately)
# Parent: redirect
GnizaWHM::UI::set_flash('success', "Backup started for schedule '$name'. Check Logs for progress."); GnizaWHM::UI::set_flash('success', "Backup started for schedule '$name'. Check Logs for progress.");
print "Status: 302 Found\r\n"; print "Status: 302 Found\r\n";
print "Location: schedules.cgi\r\n\r\n"; print "Location: schedules.cgi\r\n\r\n";