mirror of
https://github.com/MariaDB/server.git
synced 2025-01-20 22:12:30 +01:00
151 lines
3.3 KiB
Perl
151 lines
3.3 KiB
Perl
#!/usr/bin/perl
|
|
# -*- cperl -*-
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use lib 'lib';
|
|
use My::SafeProcess::Base;
|
|
use POSIX qw(WNOHANG);
|
|
|
|
###########################################################################
|
|
# Util functions
|
|
###########################################################################
|
|
|
|
#
|
|
#Print message to stderr
|
|
#
|
|
my $verbose= 0;
|
|
sub message {
|
|
if ($verbose > 0){
|
|
use Time::localtime;
|
|
my $tm= localtime();
|
|
my $timestamp= sprintf("%02d%02d%02d %2d:%02d:%02d",
|
|
$tm->year % 100, $tm->mon+1, $tm->mday,
|
|
$tm->hour, $tm->min, $tm->sec);
|
|
print STDERR $timestamp, " monitor[$$]: ", @_, "\n";
|
|
}
|
|
}
|
|
|
|
|
|
###########################################################################
|
|
# Main program
|
|
###########################################################################
|
|
|
|
my $terminated= 0;
|
|
|
|
# Protect against being killed in the middle
|
|
# of child creation, just set the terminated flag
|
|
# to make sure the child will be killed off
|
|
# when program is ready to do that
|
|
$SIG{TERM}= sub { message("!Got signal @_"); $terminated= 1; };
|
|
$SIG{INT}= sub { message("!Got signal @_"); $terminated= 1; };
|
|
|
|
my $parent_pid= getppid();
|
|
|
|
my $found_double_dash= 0;
|
|
while (my $arg= shift(@ARGV)){
|
|
|
|
if ($arg =~ /^--$/){
|
|
$found_double_dash= 1;
|
|
last;
|
|
}
|
|
elsif ($arg =~ /^--verbose$/){
|
|
$verbose= 1;
|
|
}
|
|
else {
|
|
die "Unknown option: $arg";
|
|
}
|
|
}
|
|
|
|
my $path= shift(@ARGV); # Executable
|
|
|
|
die "usage:\n" .
|
|
" safe_process.pl [opts] -- <path> [<args> [...<args_n>]]"
|
|
unless defined $path || $found_double_dash;
|
|
|
|
|
|
message("started");
|
|
#message("path: '$path'");
|
|
message("parent: $parent_pid");
|
|
|
|
# Start process to monitor
|
|
my $child_pid=
|
|
create_process(
|
|
path => $path,
|
|
args => \@ARGV,
|
|
setpgrp => 1,
|
|
);
|
|
message("Started child $child_pid");
|
|
|
|
eval {
|
|
sub handle_signal {
|
|
$terminated= 1;
|
|
message("Got signal @_");
|
|
|
|
# Ignore all signals
|
|
foreach my $name (keys %SIG){
|
|
$SIG{$name}= 'IGNORE';
|
|
}
|
|
|
|
die "signaled\n";
|
|
};
|
|
local $SIG{TERM}= \&handle_signal;
|
|
local $SIG{INT}= \&handle_signal;
|
|
local $SIG{CHLD}= sub {
|
|
message("Got signal @_");
|
|
kill(9, -$child_pid);
|
|
my $ret= waitpid($child_pid, 0);
|
|
if ($? & 127){
|
|
exit(65); # Killed by signal
|
|
}
|
|
exit($? >> 8);
|
|
};
|
|
|
|
# Monitoring loop
|
|
while(!$terminated) {
|
|
|
|
# Check if parent is still alive
|
|
if (kill(0, $parent_pid) < 1){
|
|
message("Parent is not alive anymore");
|
|
last;
|
|
}
|
|
|
|
# Wait for child to terminate but wakeup every
|
|
# second to also check that parent is still alive
|
|
my $ret_pid;
|
|
$ret_pid= waitpid($child_pid, &WNOHANG);
|
|
if ($ret_pid == $child_pid) {
|
|
# Process has exited, collect return status
|
|
my $ret_code= $? >> 8;
|
|
message("Child exit: $ret_code");
|
|
# Exit with exit status of the child
|
|
exit ($ret_code);
|
|
}
|
|
sleep(1);
|
|
}
|
|
};
|
|
if ( $@ ) {
|
|
# The monitoring loop should have been
|
|
# broken by handle_signal
|
|
warn "Unexpected: $@" unless ( $@ =~ /signaled/ );
|
|
}
|
|
|
|
# Use negative pid in order to kill the whole
|
|
# process group
|
|
#
|
|
my $ret= kill(9, -$child_pid);
|
|
message("Killed child: $child_pid, ret: $ret");
|
|
if ($ret > 0) {
|
|
message("Killed child: $child_pid");
|
|
# Wait blocking for the child to return
|
|
my $ret_pid= waitpid($child_pid, 0);
|
|
if ($ret_pid != $child_pid){
|
|
message("unexpected pid $ret_pid returned from waitpid($child_pid)");
|
|
}
|
|
}
|
|
|
|
message("DONE!");
|
|
exit (1);
|
|
|
|
|