fix(protocol): honor --timeout for protocol I/O; bound idle/session time

This commit is contained in:
2026-09-13 03:29:01 +02:00
parent 4bc84fe954
commit b16349b81e
13 changed files with 279 additions and 5 deletions
+5 -1
View File
@@ -67,7 +67,11 @@ static void config_set_defaults(Config* config) {
config->tls_ca = NULL;
config->server_host = str_dup("127.0.0.1");
config->server_port = 8080;
config->timeout = 30;
/* 0 means "--timeout not given": the transport keeps its own built-in 30 s
* socket timeout (tcp_set_timeouts ignores non-positive values) and the
* protocol layer keeps its built-in 60 s per-message deadline. A positive
* value overrides BOTH (see protocol_session_set_io_timeout). */
config->timeout = 0;
config->contimeout = 10;
config->quiet = false;
config->backup = false;
+5
View File
@@ -157,7 +157,12 @@ typedef struct Config {
char* tls_cert;
char* tls_key;
char* tls_ca;
/* --timeout: per-message I/O deadline in seconds. 0 (the default/unset
* sentinel) leaves the transport's built-in 30 s socket timeout and the
* protocol's built-in 60 s per-message deadline in place; a positive value
* overrides both. See protocol_session_set_io_timeout. */
int timeout;
/* --contimeout: connect()/accept timeout, transport layer only. */
int contimeout;
bool quiet;
bool backup;
+13 -2
View File
@@ -76,10 +76,17 @@ void protocol_session_init(ProtocolSession* session, int read_fd, int write_fd)
session->read_fd = read_fd;
session->write_fd = write_fd;
session->max_alloc = DEFAULT_MAX_ALLOC;
session->io_timeout_sec = RECEIVE_TIMEOUT_SEC;
atomic_init(&session->total_allocated_bytes, 0);
protocol_session_set_bwlimit(session, global_bwlimit());
}
void protocol_session_set_io_timeout(ProtocolSession* session, int sec) {
if (!session)
return;
session->io_timeout_sec = sec;
}
void protocol_session_set_max_alloc(ProtocolSession* session, unsigned long long max_alloc) {
if (!session)
session = bound_session ? bound_session : &legacy_io_session;
@@ -257,10 +264,11 @@ bool protocol_send_n_data(ProtocolSession* session, const void* data, size_t dat
log_debug_message(LOG_DEBUG_IO, " Sending n Data: %zu", data_size);
if (!session)
return false;
int timeout_sec = session->io_timeout_sec > 0 ? session->io_timeout_sec : SEND_TIMEOUT_SEC;
int fd = session->write_fd;
struct timespec deadline;
clock_gettime(CLOCK_MONOTONIC, &deadline);
deadline.tv_sec += SEND_TIMEOUT_SEC;
deadline.tv_sec += timeout_sec;
short wait_events = POLLOUT;
ssize_t total_bytes_send = 0;
while ((size_t)total_bytes_send < data_size) {
@@ -306,7 +314,10 @@ bool protocol_receive_n_data_timed(ProtocolSession* session, void* data, size_t
int timeout_sec);
bool protocol_receive_n_data(ProtocolSession* session, void* data, size_t data_size) {
return protocol_receive_n_data_timed(session, data, data_size, RECEIVE_TIMEOUT_SEC);
/* Honor the session's configured deadline; protocol_receive_n_data_timed
* re-applies the built-in 60 s default when the value is <= 0. */
int timeout_sec = session ? session->io_timeout_sec : 0;
return protocol_receive_n_data_timed(session, data, data_size, timeout_sec);
}
bool protocol_receive_n_data_timed(ProtocolSession* session, void* data, size_t data_size,
+11
View File
@@ -52,6 +52,12 @@ typedef struct ProtocolSession {
atomic_ullong total_allocated_bytes;
bool eight_bit_output;
unsigned long long max_alloc;
/* Per-session deadline (seconds) applied to every protocol send/receive by
* protocol_send_n_data / protocol_receive_n_data. Defaults to the built-in
* 60 s window; a value <= 0 falls back to that default. Set from the
* negotiated Config->timeout so --timeout is honored by the poll()-driven
* protocol I/O, not just the socket SO_RCVTIMEO/SO_SNDTIMEO. */
int io_timeout_sec;
} ProtocolSession;
typedef int Status;
@@ -141,6 +147,11 @@ void protocol_session_unbind(void);
void protocol_session_set_ssl(ProtocolSession* session, SSL* ssl);
void protocol_session_set_bwlimit(ProtocolSession* session, unsigned long long bytes_per_sec);
void protocol_session_set_max_alloc(ProtocolSession* session, unsigned long long max_alloc);
/* Override the per-message send/receive deadline for this session.
* `sec` <= 0 restores the built-in 60 s default (used for --timeout=0/unset).
* An explicit long deadline (e.g. the delete-ack wait) is applied per-call by
* protocol_receive_status_timed and is unaffected by this setter. */
void protocol_session_set_io_timeout(ProtocolSession* session, int sec);
void* protocol_alloc(size_t size);
void* protocol_realloc(void* ptr, size_t size);
void protocol_session_set_8_bit_output(ProtocolSession* session, bool enabled);