From 8ee33030e6a8f6117e2eec4bd14d1ac64ccceae2 Mon Sep 17 00:00:00 2001 From: ravinsp <33562092+ravinsp@users.noreply.github.com> Date: Sat, 3 Jun 2023 21:10:12 +0530 Subject: [PATCH] Contract exec timeout. --- src/conf.cpp | 2 ++ src/conf.hpp | 13 +++++++------ src/sc/sc.cpp | 10 ++++++++++ src/util/version.hpp | 4 ++-- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/conf.cpp b/src/conf.cpp index ac11899d..4043d8b5 100644 --- a/src/conf.cpp +++ b/src/conf.cpp @@ -972,6 +972,7 @@ namespace conf 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); + round_limits.insert_or_assign("exec_timeout", contract.round_limits.exec_timeout); jdoc.insert_or_assign("round_limits", round_limits); } @@ -1112,6 +1113,7 @@ namespace conf contract.round_limits.proc_cpu_seconds = jdoc["round_limits"]["proc_cpu_seconds"].as(); contract.round_limits.proc_mem_bytes = jdoc["round_limits"]["proc_mem_bytes"].as(); contract.round_limits.proc_ofd_count = jdoc["round_limits"]["proc_ofd_count"].as(); + contract.round_limits.exec_timeout = jdoc["round_limits"]["exec_timeout"].as(); } catch (const std::exception &e) { diff --git a/src/conf.hpp b/src/conf.hpp index 00c116aa..242d8d43 100644 --- a/src/conf.hpp +++ b/src/conf.hpp @@ -157,12 +157,13 @@ namespace conf struct round_limits_config { - 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. + 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. + uint64_t exec_timeout = 300000; // Contract execution timeout in ms. }; struct contract_log_config diff --git a/src/sc/sc.cpp b/src/sc/sc.cpp index f696b1f8..dca58633 100644 --- a/src/sc/sc.cpp +++ b/src/sc/sc.cpp @@ -433,6 +433,10 @@ namespace sc { util::mask_signal(); + // We record the start time of the monitoring thread to track the contract execution timeout. + const uint64_t start_time = util::get_epoch_milliseconds(); + const uint64_t exec_timeout = conf::cfg.contract.round_limits.exec_timeout; + // Prepare output poll fd list. // User out fds + control fd + NPL fd (NPL fd not available in readonly mode) const size_t out_fd_count = ctx.user_fds.size() + (ctx.args.readonly ? 1 : 2); @@ -454,6 +458,12 @@ namespace sc // Polling loop which keeps checking contract fds. while (!ctx.is_shutting_down) { + if (exec_timeout > 0 && (util::get_epoch_milliseconds() - start_time) > exec_timeout) + { + LOG_INFO << "Contract process timeout of " << exec_timeout << "ms exceeded."; + break; + } + bool messages_read = false, messages_written = false; // Reset the revents because we are reusing same pollfd list. diff --git a/src/util/version.hpp b/src/util/version.hpp index 1eb7cf30..51b74278 100644 --- a/src/util/version.hpp +++ b/src/util/version.hpp @@ -6,10 +6,10 @@ namespace version { // HotPocket version. Written to new configs and p2p/user messages. - constexpr const char *HP_VERSION = "0.6.1"; + constexpr const char *HP_VERSION = "0.6.2"; // Minimum compatible config version (this will be used to validate configs). - constexpr const char *MIN_CONFIG_VERSION = "0.5.0"; + constexpr const char *MIN_CONFIG_VERSION = "0.6.2"; // Ledger file storage version. All nodes in a cluster MUST use the same ledger version. constexpr const char *LEDGER_VERSION = "0.5.0";