package Gruntmaster::Daemon::Format::CPP; use 5.014000; use strict; use warnings; use BSD::Resource qw/setrlimit RLIMIT_AS RLIMIT_FSIZE/; use POSIX qw//; use File::Basename qw/fileparse/; use Gruntmaster::Daemon::Constants qw/TLE OLE DIED NZX/; use Log::Log4perl qw/get_logger/; use Time::HiRes qw/alarm/; use List::MoreUtils qw/natatime/; use IPC::Signal qw/sig_name sig_num/; use IPC::Open3 qw/open3/; use File::Spec::Functions qw/devnull/; use Fcntl qw/F_GETFD F_SETFD FD_CLOEXEC/; our $VERSION = '0.001'; ################################################## sub prepare{ my $name = $_[0]; my $basename = fileparse $name, qr/\.[^.]*/; get_logger->trace("Preparing file $name..."); open my $devnull, devnull; open my $errors, '>compile-error'; my $ret = open3 $devnull, $errors, $errors, 'g++', '-o', $basename, $name; local $SIG{ALRM} = sub {kill KILL => $ret}; alarm 5; wait; close $devnull; close $errors; die 'Compile error' if $? } sub run{ my ($name, %args) = @_; my $basename = fileparse $name, qr/\.[^.]*/; my $ret = fork // die 'Cannot fork'; if ($ret) { my $tle; local $SIG{ALRM} = sub { kill KILL => $ret; $tle = 1}; alarm $args{timeout} if exists $args{timeout}; wait; alarm 0; my $sig = $? & 127; my $signame = sig_name $sig; die [TLE, "Time Limit Exceeded"] if $tle; die [OLE, 'Output Limit Exceeded'] if $sig && $signame eq 'XFSZ'; die [DIED, "Crash (SIG$signame)"] if $sig; die [NZX, "Non-zero exit status: " . ($? >> 8)] if $?; } else { $^F = 50; POSIX::close $_ for 0, 1, 3 .. $^F; my @fds = exists $args{fds} ? @{$args{fds}} : (); get_logger->trace("Running $basename with fds ". join ' ', @fds); my $it = natatime 2, @fds; while (my ($fd, $file) = $it->()) { open my $fh, $file or die $!; my $oldfd = fileno $fh; if ($oldfd != $fd) { POSIX::dup2 $oldfd, $fd or die $!; POSIX::close $oldfd or die $!; } } # POSIX::close 2; setrlimit RLIMIT_AS, $args{mlimit}, $args{mlimit} if exists $args{mlimit}; setrlimit RLIMIT_FSIZE, $args{olimit}, $args{olimit} if exists $args{olimit}; exec "./$basename", exists $args{args} ? @{$args{args}} : (); } } 1