diff --git a/src/rpc/scgi_task.cc b/src/rpc/scgi_task.cc index 647851b7..ed7a5e2d 100644 --- a/src/rpc/scgi_task.cc +++ b/src/rpc/scgi_task.cc @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "control.h" @@ -27,6 +28,8 @@ namespace rpc { SCgiTask::SCgiTask() : m_callback_id(torrent::system::make_callback_id()) { + m_task_timeout.slot() = [this]() { close(); }; + reset_file_descriptor(); } @@ -50,6 +53,8 @@ SCgiTask::open(SCgi* parent, int fd) { torrent::this_thread::poll()->open(this); torrent::this_thread::poll()->insert_read(this); + torrent::this_thread::scheduler()->update_wait_for_ceil_seconds(&m_task_timeout, timeout_request); + auto lock = std::lock_guard(m_result_mutex); // Leave room for terminating nul byte for parsing the header. @@ -61,6 +66,8 @@ SCgiTask::cancel_open() { if (!is_open()) return; + torrent::this_thread::scheduler()->erase(&m_task_timeout); + torrent::this_thread::poll()->remove_and_close(this); torrent::fd_close(file_descriptor()); @@ -72,6 +79,8 @@ SCgiTask::close() { if (!is_open()) return; + torrent::this_thread::scheduler()->erase(&m_task_timeout); + torrent::system::cancel_callback_and_wait(m_callback_id, scgi_thread::thread(), torrent::main_thread::thread()); torrent::runtime::socket_manager()->close_event_or_throw(this, [this]() { @@ -158,6 +167,8 @@ SCgiTask::event_read() { torrent::this_thread::poll()->remove_read(this); + torrent::this_thread::scheduler()->update_wait_for_ceil_seconds(&m_task_timeout, timeout_request); + if (m_parent->log_fd() >= 0) { [[maybe_unused]] int result; diff --git a/src/rpc/scgi_task.h b/src/rpc/scgi_task.h index bffe8101..33b7c181 100644 --- a/src/rpc/scgi_task.h +++ b/src/rpc/scgi_task.h @@ -1,10 +1,12 @@ #ifndef RTORRENT_RPC_SCGI_TASK_H #define RTORRENT_RPC_SCGI_TASK_H +#include #include #include #include #include +#include namespace rpc { @@ -16,6 +18,8 @@ public: static constexpr int max_header_size = 2000; static constexpr int max_content_size = (2 << 23); + static constexpr auto timeout_request = std::chrono::seconds(60); + enum ContentType { XML, JSON }; SCgiTask(); @@ -54,8 +58,9 @@ private: void plaintext_response(const char* buffer, uint32_t content_length); void gzip_response(const char* buffer, uint32_t content_length); - SCgi* m_parent{}; - torrent::system::callback_id m_callback_id; + SCgi* m_parent{}; + torrent::system::callback_id m_callback_id; + torrent::system::SchedulerEntry m_task_timeout; std::mutex m_result_mutex;