mirror of
https://github.com/renbaoshuo/S2OJ.git
synced 2024-11-22 01:48:41 +00:00
feat(judger): support non-integer time limit (#15)
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
本 Pull Request 通过将时间限制解析为浮点数的方式,实现了对非整数时间限制的支持。 --- ref: https://github.com/vfleaking/uoj/pull/100
This commit is contained in:
commit
f12b3cf84e
@ -633,6 +633,23 @@ int conf_int(const string &key, int num, const int &val) {
|
|||||||
int conf_int(const string &key) {
|
int conf_int(const string &key) {
|
||||||
return conf_int(key, 0);
|
return conf_int(key, 0);
|
||||||
}
|
}
|
||||||
|
double conf_double(const string &key, const double &val) {
|
||||||
|
if (config.count(key) == 0) {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
return stod(config[key]);
|
||||||
|
}
|
||||||
|
double conf_double(const string &key, int num, const double &val) {
|
||||||
|
ostringstream sout;
|
||||||
|
sout << key << "_" << num;
|
||||||
|
if (config.count(sout.str()) == 0) {
|
||||||
|
return conf_double(key, val);
|
||||||
|
}
|
||||||
|
return stod(config[sout.str()]);
|
||||||
|
}
|
||||||
|
double conf_double(const string &key) {
|
||||||
|
return conf_double(key, 0);
|
||||||
|
}
|
||||||
string conf_file_name_with_num(string s, int num) {
|
string conf_file_name_with_num(string s, int num) {
|
||||||
ostringstream name;
|
ostringstream name;
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
@ -664,10 +681,10 @@ runp::limits_t conf_run_limit(string pre, const int &num, const runp::limits_t &
|
|||||||
pre += "_";
|
pre += "_";
|
||||||
}
|
}
|
||||||
runp::limits_t limits;
|
runp::limits_t limits;
|
||||||
limits.time = conf_int(pre + "time_limit", num, val.time);
|
limits.time = conf_double(pre + "time_limit", num, val.time);
|
||||||
limits.memory = conf_int(pre + "memory_limit", num, val.memory);
|
limits.memory = conf_int(pre + "memory_limit", num, val.memory);
|
||||||
limits.output = conf_int(pre + "output_limit", num, val.output);
|
limits.output = conf_int(pre + "output_limit", num, val.output);
|
||||||
limits.real_time = conf_int(pre + "real_time_limit", num, val.real_time);
|
limits.real_time = conf_double(pre + "real_time_limit", num, val.real_time);
|
||||||
limits.stack = conf_int(pre + "stack_limit", num, val.stack);
|
limits.stack = conf_int(pre + "stack_limit", num, val.stack);
|
||||||
return limits;
|
return limits;
|
||||||
}
|
}
|
||||||
|
@ -501,6 +501,23 @@ int conf_int(const string &key, int num, const int &val) {
|
|||||||
int conf_int(const string &key) {
|
int conf_int(const string &key) {
|
||||||
return conf_int(key, 0);
|
return conf_int(key, 0);
|
||||||
}
|
}
|
||||||
|
double conf_double(const string &key, const double &val) {
|
||||||
|
if (uconfig.count(key) == 0) {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
return stod(uconfig[key]);
|
||||||
|
}
|
||||||
|
double conf_double(const string &key, int num, const double &val) {
|
||||||
|
ostringstream sout;
|
||||||
|
sout << key << "_" << num;
|
||||||
|
if (uconfig.count(sout.str()) == 0) {
|
||||||
|
return conf_double(key, val);
|
||||||
|
}
|
||||||
|
return stod(uconfig[sout.str()]);
|
||||||
|
}
|
||||||
|
double conf_double(const string &key) {
|
||||||
|
return conf_double(key, 0);
|
||||||
|
}
|
||||||
string conf_file_name_with_num(string s, int num) {
|
string conf_file_name_with_num(string s, int num) {
|
||||||
ostringstream name;
|
ostringstream name;
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
@ -530,10 +547,10 @@ runp::limits_t conf_run_limit(string pre, const int &num, const runp::limits_t &
|
|||||||
pre += "_";
|
pre += "_";
|
||||||
}
|
}
|
||||||
runp::limits_t limits;
|
runp::limits_t limits;
|
||||||
limits.time = conf_int(pre + "time_limit", num, val.time);
|
limits.time = conf_double(pre + "time_limit", num, val.time);
|
||||||
limits.memory = conf_int(pre + "memory_limit", num, val.memory);
|
limits.memory = conf_int(pre + "memory_limit", num, val.memory);
|
||||||
limits.output = conf_int(pre + "output_limit", num, val.output);
|
limits.output = conf_int(pre + "output_limit", num, val.output);
|
||||||
limits.real_time = conf_int(pre + "real_time_limit", num, val.real_time);
|
limits.real_time = conf_double(pre + "real_time_limit", num, val.real_time);
|
||||||
limits.stack = conf_int(pre + "stack_limit", num, val.real_time);
|
limits.stack = conf_int(pre + "stack_limit", num, val.real_time);
|
||||||
return limits;
|
return limits;
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include <cmath>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
@ -7,6 +8,7 @@
|
|||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
#define UOJ_GCC "/usr/bin/gcc-11"
|
#define UOJ_GCC "/usr/bin/gcc-11"
|
||||||
#define UOJ_GPLUSPLUS "/usr/bin/g++-11"
|
#define UOJ_GPLUSPLUS "/usr/bin/g++-11"
|
||||||
@ -20,6 +22,11 @@
|
|||||||
std::string escapeshellarg(int arg) {
|
std::string escapeshellarg(int arg) {
|
||||||
return std::to_string(arg);
|
return std::to_string(arg);
|
||||||
}
|
}
|
||||||
|
std::string escapeshellarg(double arg) {
|
||||||
|
std::ostringstream sout;
|
||||||
|
sout << std::setprecision(15) << arg;
|
||||||
|
return sout.str();
|
||||||
|
}
|
||||||
std::string escapeshellarg(const std::string &arg) {
|
std::string escapeshellarg(const std::string &arg) {
|
||||||
std::string res = "'";
|
std::string res = "'";
|
||||||
for (char c : arg) {
|
for (char c : arg) {
|
||||||
@ -133,14 +140,14 @@ namespace runp {
|
|||||||
fs::path run_path;
|
fs::path run_path;
|
||||||
|
|
||||||
struct limits_t {
|
struct limits_t {
|
||||||
int time;
|
double time;
|
||||||
int memory;
|
int memory;
|
||||||
int output;
|
int output;
|
||||||
int real_time;
|
double real_time;
|
||||||
int stack;
|
int stack;
|
||||||
|
|
||||||
limits_t() = default;
|
limits_t() = default;
|
||||||
limits_t(const int &_time, const int &_memory, const int &_output)
|
limits_t(const double &_time, const int &_memory, const int &_output)
|
||||||
: time(_time), memory(_memory), output(_output), real_time(-1), stack(-1) {
|
: time(_time), memory(_memory), output(_output), real_time(-1), stack(-1) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -388,6 +395,32 @@ namespace runp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief convert a time t to timeval. Assume t <= 1000. Accurate to ms.
|
||||||
|
*
|
||||||
|
* @param t time in double
|
||||||
|
* @return timeval
|
||||||
|
*/
|
||||||
|
timeval double_to_timeval(const double &t) {
|
||||||
|
long tl = round(t * 1000);
|
||||||
|
long tl_sec = tl / 1000;
|
||||||
|
long tl_usec = tl % 1000 * 1000;
|
||||||
|
return {tl_sec, tl_usec};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief convert a time t to timespec. Assume t <= 1000. Accurate to ms.
|
||||||
|
*
|
||||||
|
* @param t time in double
|
||||||
|
* @return timespec
|
||||||
|
*/
|
||||||
|
timespec double_to_timespec(const double &t) {
|
||||||
|
long tl = round(t * 1000);
|
||||||
|
long tl_sec = tl / 1000;
|
||||||
|
long tl_nsec = tl % 1000 * 1'000'000;
|
||||||
|
return {tl_sec, tl_nsec};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace runp::interaction {
|
namespace runp::interaction {
|
||||||
|
@ -51,10 +51,10 @@ error_t run_program_argp_parse_opt (int key, char *arg, struct argp_state *state
|
|||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'T':
|
case 'T':
|
||||||
config->limits.time = atoi(arg);
|
config->limits.time = round(stod(arg) * 1000) / 1000;
|
||||||
break;
|
break;
|
||||||
case 'R':
|
case 'R':
|
||||||
config->limits.real_time = atoi(arg);
|
config->limits.real_time = round(stod(arg) * 1000) / 1000;
|
||||||
break;
|
break;
|
||||||
case 'M':
|
case 'M':
|
||||||
config->limits.memory = atoi(arg);
|
config->limits.memory = atoi(arg);
|
||||||
@ -201,10 +201,17 @@ void set_limit(int r, int rcur, int rmax = -1) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_user_cpu_time_limit(int tl) {
|
void set_user_cpu_time_limit(double tl) {
|
||||||
struct itimerval val;
|
itimerval val;
|
||||||
val.it_value = {tl, 100 * 1000};
|
val.it_value = runp::double_to_timeval(tl);
|
||||||
val.it_interval = {0, 100 * 1000};
|
val.it_interval = {0, 100'000};
|
||||||
|
|
||||||
|
val.it_value.tv_usec += 100'000;
|
||||||
|
if (val.it_value.tv_usec >= 1'000'000) {
|
||||||
|
val.it_value.tv_sec++;
|
||||||
|
val.it_value.tv_usec -= 1'000'000;
|
||||||
|
}
|
||||||
|
|
||||||
setitimer(ITIMER_VIRTUAL, &val, NULL);
|
setitimer(ITIMER_VIRTUAL, &val, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,7 +311,7 @@ struct rusage *ruse0p = NULL;
|
|||||||
bool has_real_TLE() {
|
bool has_real_TLE() {
|
||||||
struct timeval elapsed;
|
struct timeval elapsed;
|
||||||
timersub(&end_time, &start_time, &elapsed);
|
timersub(&end_time, &start_time, &elapsed);
|
||||||
return elapsed.tv_sec >= run_program_config.limits.real_time;
|
return elapsed.tv_sec + elapsed.tv_usec / 1'000'000. >= run_program_config.limits.real_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rp_children_pos(pid_t pid) {
|
int rp_children_pos(pid_t pid) {
|
||||||
@ -630,9 +637,12 @@ void dispatch_event(run_event&& e) {
|
|||||||
if (rp_timer_pid == -1) {
|
if (rp_timer_pid == -1) {
|
||||||
runp::result(runp::RS_JGF, "error code: FKFAL2").dump_and_exit(); // fork failed
|
runp::result(runp::RS_JGF, "error code: FKFAL2").dump_and_exit(); // fork failed
|
||||||
} else if (rp_timer_pid == 0) {
|
} else if (rp_timer_pid == 0) {
|
||||||
struct timespec ts;
|
struct timespec ts = runp::double_to_timespec(run_program_config.limits.real_time);
|
||||||
ts.tv_sec = run_program_config.limits.real_time;
|
ts.tv_nsec += 100'000'000;
|
||||||
ts.tv_nsec = 100 * 1000000;
|
if (ts.tv_nsec >= 1'000'000'000) {
|
||||||
|
ts.tv_sec += 1;
|
||||||
|
ts.tv_nsec -= 1'000'000'000;
|
||||||
|
}
|
||||||
nanosleep(&ts, NULL);
|
nanosleep(&ts, NULL);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <sys/user.h>
|
#include <sys/user.h>
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <argp.h>
|
#include <argp.h>
|
||||||
|
Loading…
Reference in New Issue
Block a user