|
|
@ -1,207 +0,0 @@
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <sys/resource.h>
|
|
|
|
|
|
|
|
#include <jsoncpp/json/json.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "./comm/util.hpp"
|
|
|
|
|
|
|
|
#include "compile.hpp"
|
|
|
|
|
|
|
|
#include "Runner.hpp"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace ns_compile_run
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// 协调程序的编译和运行
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
enum STATUS
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
EmptyCodeError = -2,
|
|
|
|
|
|
|
|
CompileFailError
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Compile_Run
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
Compile_Run()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
~Compile_Run()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// in_json中包含:
|
|
|
|
|
|
|
|
// 1、code:用户提交的代码
|
|
|
|
|
|
|
|
// 2、input:用户给自己提交的代码所做的输入,不做处理
|
|
|
|
|
|
|
|
// 3、cpu_limit:CPU运行时间限制
|
|
|
|
|
|
|
|
// 4、mem_limit:内存限制,即空间限制
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void start(const std::string &in_json, std::string *out_json)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// 程序状态
|
|
|
|
|
|
|
|
int status = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 1.把输入的in_json反序列化
|
|
|
|
|
|
|
|
Json::Value in_value;
|
|
|
|
|
|
|
|
Json::Reader reader;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
reader.parse(in_json, in_value);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string code = in_value["code"].asString();
|
|
|
|
|
|
|
|
// std::cout << "输出code代码: " << std::endl;
|
|
|
|
|
|
|
|
// std::cout<<code<<std::endl;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 代码为空的情况,直接处理结果
|
|
|
|
|
|
|
|
if (code.size() == 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
status = EmptyCodeError;
|
|
|
|
|
|
|
|
getOutJson(status, out_json, "");
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string input = in_value["input"].asString();
|
|
|
|
|
|
|
|
rlim_t cpu_limit = in_value["cpu_limit"].asInt64();
|
|
|
|
|
|
|
|
rlim_t mem_limit = in_value["mem_limit"].asInt64();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 2.生成一个随机且唯一的文件名
|
|
|
|
|
|
|
|
std::string file_name = ns_util::nameUtil::getUniqueName();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 3.把code导入文件中
|
|
|
|
|
|
|
|
if (!ns_util::fileUtil::writeFile(ns_util::pathUtil::src(file_name), code))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
lg(Error, "写入源文件失败, errno: %d, strerror: %s\n", errno, strerror(errno));
|
|
|
|
|
|
|
|
exit(2);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 4.编译代码
|
|
|
|
|
|
|
|
ns_compile::Compiler compiler;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 代码编译失败
|
|
|
|
|
|
|
|
if (!compiler.compile(file_name))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
status = CompileFailError;
|
|
|
|
|
|
|
|
getOutJson(status, out_json, file_name);
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 5.运行代码
|
|
|
|
|
|
|
|
// ns_run::Runner runner;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
status = ns_run::Runner::run(file_name, cpu_limit, mem_limit);
|
|
|
|
|
|
|
|
// std::cout<<status<<std::endl;
|
|
|
|
|
|
|
|
getOutJson(status, out_json, file_name);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// out_json中包含:
|
|
|
|
|
|
|
|
// 1、status:状态码
|
|
|
|
|
|
|
|
// 2、reason:请求结果
|
|
|
|
|
|
|
|
// (选填):
|
|
|
|
|
|
|
|
// 3、stdout:用户程序运行完毕后的结果
|
|
|
|
|
|
|
|
// 4、stderr:用户程序如果运行出错的错误结果
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
static void getOutJson(int code, std::string *out_json, const std::string &file_name)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
Json::Value out_value;
|
|
|
|
|
|
|
|
// std::cout<<"getOutJson的code:"<<std::endl;
|
|
|
|
|
|
|
|
out_value["status"] = code;
|
|
|
|
|
|
|
|
out_value["reason"] = codeToDesc(code, file_name);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (code == 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// 程序执行完成
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string stdout_file_name = ns_util::pathUtil::Stdout(file_name);
|
|
|
|
|
|
|
|
std::string stderr_file_name = ns_util::pathUtil::Stderr(file_name);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string stdout_file;
|
|
|
|
|
|
|
|
std::string stderr_file;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 将来要给用户看的,所以要换行符
|
|
|
|
|
|
|
|
ns_util::fileUtil::readFile(stdout_file_name, &stdout_file, true);
|
|
|
|
|
|
|
|
ns_util::fileUtil::readFile(stderr_file_name, &stderr_file, true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
out_value["stdout"] = stdout_file;
|
|
|
|
|
|
|
|
out_value["stderr"] = stderr_file;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 调试用StyledWriter,正式项目用FastWriter
|
|
|
|
|
|
|
|
Json::StyledWriter writer;
|
|
|
|
|
|
|
|
*out_json = writer.write(out_value);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
removeTempFile(file_name);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static std::string codeToDesc(int code, const std::string &file_name)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
switch (code)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
case 0:
|
|
|
|
|
|
|
|
return "Successful!";
|
|
|
|
|
|
|
|
case EmptyCodeError:
|
|
|
|
|
|
|
|
return "Empty code!";
|
|
|
|
|
|
|
|
case CompileFailError:
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// 编译出错需要知道出错的报错,而报错存再.compile_error文件中
|
|
|
|
|
|
|
|
std::string compile_error_file_name = ns_util::pathUtil::compilerError(file_name);
|
|
|
|
|
|
|
|
std::string compile_error_file;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 报错是要给用户看的,所以也需要加换行符
|
|
|
|
|
|
|
|
ns_util::fileUtil::readFile(compile_error_file_name, &compile_error_file, true);
|
|
|
|
|
|
|
|
return compile_error_file;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
case SIGABRT: // 6
|
|
|
|
|
|
|
|
return "Memory out of range!";
|
|
|
|
|
|
|
|
case SIGFPE: // 8
|
|
|
|
|
|
|
|
return "Floating overflow!";
|
|
|
|
|
|
|
|
case SIGXCPU: // 24
|
|
|
|
|
|
|
|
return "CPU timeout!";
|
|
|
|
|
|
|
|
case SIGSEGV: // 11
|
|
|
|
|
|
|
|
return "Segmentation Fault!";
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return "Unknown error, status code: " + std::to_string(code);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void removeTempFile(const std::string &file_name)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// 要清除的有.cpp .exe .compile_error .stdin .stdout .stderr
|
|
|
|
|
|
|
|
// 可以使用unlink 或 remove系统调用来删除文件
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string src = ns_util::pathUtil::src(file_name);
|
|
|
|
|
|
|
|
if (ns_util::fileUtil::isFileExist(src))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
unlink(src.c_str());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string exe = ns_util::pathUtil::exe(file_name);
|
|
|
|
|
|
|
|
if (ns_util::fileUtil::isFileExist(exe))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
unlink(exe.c_str());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string compile_error = ns_util::pathUtil::compilerError(file_name);
|
|
|
|
|
|
|
|
if (ns_util::fileUtil::isFileExist(compile_error))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
unlink(compile_error.c_str());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string Stdin = ns_util::pathUtil::Stdin(file_name);
|
|
|
|
|
|
|
|
if (ns_util::fileUtil::isFileExist(Stdin))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
unlink(Stdin.c_str());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string Stdout = ns_util::pathUtil::Stdout(file_name);
|
|
|
|
|
|
|
|
if (ns_util::fileUtil::isFileExist(Stdout))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
unlink(Stdout.c_str());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string Stderr = ns_util::pathUtil::Stderr(file_name);
|
|
|
|
|
|
|
|
if (ns_util::fileUtil::isFileExist(Stderr))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
unlink(Stderr.c_str());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|