Contract process resource limits. (#243)

This commit is contained in:
Ravin Perera
2021-02-15 16:36:10 +05:30
committed by GitHub
parent 3783c687a2
commit 4c4e109233
7 changed files with 83 additions and 8 deletions

View File

@@ -859,6 +859,9 @@ namespace conf
round_limits.insert_or_assign("user_input_bytes", contract.round_limits.user_input_bytes);
round_limits.insert_or_assign("user_output_bytes", contract.round_limits.user_output_bytes);
round_limits.insert_or_assign("npl_output_bytes", contract.round_limits.npl_output_bytes);
round_limits.insert_or_assign("proc_cpu_seconds", contract.round_limits.proc_cpu_seconds);
round_limits.insert_or_assign("proc_mem_bytes", contract.round_limits.proc_mem_bytes);
round_limits.insert_or_assign("proc_ofd_count", contract.round_limits.proc_ofd_count);
jdoc.insert_or_assign("round_limits", round_limits);
}
@@ -945,6 +948,9 @@ namespace conf
contract.round_limits.user_input_bytes = jdoc["round_limits"]["user_input_bytes"].as<size_t>();
contract.round_limits.user_output_bytes = jdoc["round_limits"]["user_output_bytes"].as<size_t>();
contract.round_limits.npl_output_bytes = jdoc["round_limits"]["npl_output_bytes"].as<size_t>();
contract.round_limits.proc_cpu_seconds = jdoc["round_limits"]["proc_cpu_seconds"].as<size_t>();
contract.round_limits.proc_mem_bytes = jdoc["round_limits"]["proc_mem_bytes"].as<size_t>();
contract.round_limits.proc_ofd_count = jdoc["round_limits"]["proc_ofd_count"].as<size_t>();
}
catch (const std::exception &e)
{

View File

@@ -90,6 +90,9 @@ namespace conf
size_t user_input_bytes = 0; // Max contract input bytes per user per round.
size_t user_output_bytes = 0; // Max contract output bytes per user per round.
size_t npl_output_bytes = 0; // Max npl output bytes per round.
size_t proc_cpu_seconds = 0; // Max CPU time the contract process can consume.
size_t proc_mem_bytes = 0; // Max memory the contract process can allocate.
size_t proc_ofd_count = 0; // Max no. of open file descriptors the contract process can allocate.
};
struct contract_config

View File

@@ -38,6 +38,7 @@
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>

View File

@@ -98,6 +98,13 @@ namespace sc
// Set up the process environment and overlay the contract binary program with execv().
// Set process resource limits.
if (set_process_rlimits() == -1)
{
std::cerr << errno << ": Failed to set contract process resource limits." << (ctx.args.readonly ? " (rdonly)" : "") << "\n";
exit(1);
}
// Close all fds unused by SC process.
close_unused_fds(ctx, false);
@@ -153,6 +160,33 @@ namespace sc
return ret;
}
int set_process_rlimits()
{
rlimit lim;
if (conf::cfg.contract.round_limits.proc_cpu_seconds > 0)
{
lim.rlim_cur = lim.rlim_max = conf::cfg.contract.round_limits.proc_cpu_seconds;
if (setrlimit(RLIMIT_CPU, &lim) == -1)
return -1;
}
if (conf::cfg.contract.round_limits.proc_mem_bytes > 0)
{
lim.rlim_cur = lim.rlim_max = conf::cfg.contract.round_limits.proc_mem_bytes;
if (setrlimit(RLIMIT_DATA, &lim) == -1)
return -1;
}
if (conf::cfg.contract.round_limits.proc_ofd_count > 0)
{
lim.rlim_cur = lim.rlim_max = conf::cfg.contract.round_limits.proc_ofd_count;
if (setrlimit(RLIMIT_NOFILE, &lim) == -1)
return -1;
}
return 0;
}
/**
* Checks whether the contract process has exited.
* @param ctx Contract execution context.
@@ -185,7 +219,7 @@ namespace sc
}
else
{
LOG_ERROR << "Contract process" << (ctx.args.readonly ? " (rdonly)" : "") << " ended with code " << WEXITSTATUS(scstatus);
LOG_ERROR << "Contract process" << (ctx.args.readonly ? " (rdonly)" : "") << " ended prematurely with code " << WEXITSTATUS(scstatus);
return -1;
}
}

View File

@@ -143,6 +143,8 @@ namespace sc
//------Internal-use functions for this namespace.
int set_process_rlimits();
int check_contract_exited(execution_context &ctx, const bool block);
int start_hpfs_session(execution_context &ctx);