From ddceb393c90f620dd194c22e5e85d8c9fe87ee34 Mon Sep 17 00:00:00 2001 From: Marius Gavrilescu Date: Thu, 9 Jan 2014 22:22:49 +0200 Subject: [PATCH] Refactor Format --- lib/Gruntmaster/Daemon.pm | 21 +++++++-- lib/Gruntmaster/Daemon/Format.pm | 66 ++++++++++++++++++++++++++ lib/Gruntmaster/Daemon/Format/CPP.pm | 69 ---------------------------- 3 files changed, 83 insertions(+), 73 deletions(-) create mode 100644 lib/Gruntmaster/Daemon/Format.pm delete mode 100644 lib/Gruntmaster/Daemon/Format/CPP.pm diff --git a/lib/Gruntmaster/Daemon.pm b/lib/Gruntmaster/Daemon.pm index ccf9e4e..e9114c8 100644 --- a/lib/Gruntmaster/Daemon.pm +++ b/lib/Gruntmaster/Daemon.pm @@ -8,6 +8,7 @@ our $VERSION = '0.001'; use Gruntmaster::Daemon::Constants qw/ERR/; use Gruntmaster::Daemon::Base qw/watch/; +use Gruntmaster::Daemon::Format qw/mkrun/; use Gruntmaster::Page qw/generate/; use Fcntl qw/:flock/; @@ -36,16 +37,29 @@ sub safe_can { safe_can_nodie @_ or get_logger->logdie("No such \l$type: '$name'"); } +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, undef, 'gruntmaster-compile', CPP => $basename, $name; + waitpid $ret, 0; + close $devnull; + close $errors; + die 'Compile error' if $? +} + sub prepare_files{ my ($dir, $meta) = @_; for my $file (values $meta->{files}) { my ($format, $name) = @{$file}{qw/format name/}; - my $prepare = safe_can Format => prepare => $format; - $file->{run} = safe_can Format => run => $format; + $file->{run} = mkrun($format); die "No such file: '$name'" unless -e $name; - $prepare->($name); + prepare $name; } } @@ -117,7 +131,6 @@ sub process{ # Clean up get_logger->info("Job result: " . $meta->{result_text}); - delete $meta->{files}{$_}{run} for keys $meta->{files}; $meta->{results} = \@full_results if scalar @full_results; DumpFile "meta.yml", $meta; for (<*>) { diff --git a/lib/Gruntmaster/Daemon/Format.pm b/lib/Gruntmaster/Daemon/Format.pm new file mode 100644 index 0000000..948e25a --- /dev/null +++ b/lib/Gruntmaster/Daemon/Format.pm @@ -0,0 +1,66 @@ +package Gruntmaster::Daemon::Format; + +use 5.014000; +use strict; +use warnings; +use parent qw/Exporter/; + +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'; +our @EXPORT_OK = qw/mkrun/; + +################################################## + +sub command_and_args{ + my ($format, $basename) = @_; + return "./$basename" if $format eq 'CPP'; + die +} + +sub mkrun{ + my $format = shift; + sub{ + 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 { + my @fds = exists $args{fds} ? @{$args{fds}} : (); + $^F = 50; + POSIX::close $_ for 0 .. $^F; + 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 $!; + } + } + exec 'gruntmaster-exec', $args{mlimit} // 0, $args{olimit} // 0, command_and_args($format, $basename), exists $args{args} ? @{$args{args}} : (); + } + } +} + +1 diff --git a/lib/Gruntmaster/Daemon/Format/CPP.pm b/lib/Gruntmaster/Daemon/Format/CPP.pm deleted file mode 100644 index 96e9dda..0000000 --- a/lib/Gruntmaster/Daemon/Format/CPP.pm +++ /dev/null @@ -1,69 +0,0 @@ -package Gruntmaster::Daemon::Format::CPP; - -use 5.014000; -use strict; -use warnings; - -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, undef, 'gruntmaster-compile', CPP => $basename, $name; - waitpid $ret, 0; - 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 { - my @fds = exists $args{fds} ? @{$args{fds}} : (); - $^F = 50; - POSIX::close $_ for 0 .. $^F; - 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 $!; - } - } - exec 'gruntmaster-exec', $args{mlimit} // 0, $args{olimit} // 0, "./$basename", exists $args{args} ? @{$args{args}} : (); - } -} - -1 -- 2.39.2