The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
package Watchdog;

use strict;
use warnings;

use base 'Exporter';
our $VERSION = 0.01;
our @EXPORT_OK = qw(sys sys_for_watchdog);

use Storable;

sub sys {
    my ( $cmd, $temp_out_fn ) = @_;

    my $output;
    $temp_out_fn = '.out' unless $temp_out_fn;
    open my $oldout, ">&STDOUT"     or die "Can't dup STDOUT: $!";
    open OLDERR,     ">&", \*STDERR or die "Can't dup STDERR: $!";

    open STDOUT, '>', $temp_out_fn or die "Can't redirect STDOUT to '$temp_out_fn': $! $@";
    open STDERR, ">&STDOUT"     or die "Can't dup STDOUT: $!";

    select STDERR; $| = 1;      # make unbuffered
    select STDOUT; $| = 1;      # make unbuffered

    my $status = system($cmd);

    close STDOUT;
    close STDERR;

    open STDOUT, ">&", $oldout or die "Can't dup \$oldout: $!";
    open STDERR, ">&OLDERR"    or die "Can't dup OLDERR: $!";

    unless ( open( FH_STDOUT, "<$temp_out_fn") ) {
        carp("File $temp_out_fn not open!");
        unlink $temp_out_fn;
        next;
    }
    {
        local $/ = undef;
        $output = <FH_STDOUT>;
    }
    close FH_STDOUT;
    return ( $status, $output );
}


sub sys_for_watchdog {
    my ( $cmd, $log_fn, $timeout, $sleep ) = @_; 

    die "cmd is mandatory" unless defined $cmd;
    $log_fn = $cmd . '.log' unless defined $log_fn;
    $timeout = 5*60 unless defined $timeout;

    my $ipc_fn = '../watchdog-setting.bin';

    if ( -e $ipc_fn ) {
        print "found '$ipc_fn', probably already running\n";
#        exit 0;
    }
    print "running '$cmd' ...\n";

    my $info = {
        'log_fn'  => $log_fn,
        'pid'     => $$,
        'cmd'     => $cmd,
        'timeout' => $timeout,
    };
    $info->{'sleep'} = $sleep if defined $sleep;
    store( $info, $ipc_fn ) or die "store failed\n$!\n$@";

=head todo
=pod
    sub catch_sig {
        my $signame = shift;
        print "captured $signame\n";
        unlink $ipc_fn;
        exit;
    }

    foreach my $sig ( qw/QUIT KILL CHILD/ ) {
        $SIG{$sig} = \&catch_sig;
    }
    #print dump( \%SIG );
=cut

    my ( $status, $output ) = sys( $cmd, $log_fn );

    unlink $ipc_fn;
    while ( -e $ipc_fn ) {
        print "trying to unlink $ipc_fn\n";
        sleep 1;
        unlink $ipc_fn;
    }
    print ( ( $status ) ? "finished, but exit code is $status\n" : "finished ok\n" );
    return ( $status, $output );
}

1;