From ee30cf3b1df749241b8ed479d7b3558af81b27bf Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 12 Jun 2005 02:42:40 +0000 Subject: r7497: add timeouts to all rpc requests. The default timeout is 60 seconds. This should prevent the problem I am seeing on a solaris box where a rpc request gets stuck forever (This used to be commit c24ab34813d675b9b81f3062fb6f30aae5697805) --- source4/librpc/rpc/dcerpc.c | 42 ++++++++++++++++++++++++++++++++++++++++ source4/librpc/rpc/dcerpc.h | 6 ++++++ source4/librpc/rpc/dcerpc_util.c | 1 + 3 files changed, 49 insertions(+) (limited to 'source4/librpc/rpc') diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c index 284a3c8841..fa7fe728d4 100644 --- a/source4/librpc/rpc/dcerpc.c +++ b/source4/librpc/rpc/dcerpc.c @@ -110,6 +110,7 @@ struct dcerpc_pipe *dcerpc_pipe_init(TALLOC_CTX *mem_ctx) p->last_fault_code = 0; p->context_id = 0; + p->request_timeout = DCERPC_REQUEST_TIMEOUT; ZERO_STRUCT(p->syntax); ZERO_STRUCT(p->transfer_syntax); @@ -520,6 +521,17 @@ static void full_request_recv(struct dcerpc_connection *c, DATA_BLOB *blob, state->reply_blob = NULL; } +/* + handle timeouts of full dcerpc requests +*/ +static void dcerpc_full_timeout_handler(struct event_context *ev, struct timed_event *te, + struct timeval t, void *private) +{ + struct full_request_state *state = talloc_get_type(private, + struct full_request_state); + state->status = NT_STATUS_IO_TIMEOUT; +} + /* perform a single pdu synchronous request - used for the bind code this cannot be mixed with normal async requests @@ -547,6 +559,10 @@ static NTSTATUS full_request(struct dcerpc_connection *c, return status; } + event_add_timed(c->transport.event_context(c), state, + timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0), + dcerpc_full_timeout_handler, state); + while (NT_STATUS_IS_OK(state->status) && state->reply_blob) { struct event_context *ctx = c->transport.event_context(c); if (event_loop_once(ctx) != 0) { @@ -830,6 +846,26 @@ static void dcerpc_request_recv_data(struct dcerpc_connection *c, } } +/* + handle timeouts of individual dcerpc requests +*/ +static void dcerpc_timeout_handler(struct event_context *ev, struct timed_event *te, + struct timeval t, void *private) +{ + struct rpc_request *req = talloc_get_type(private, struct rpc_request); + + if (req->state != RPC_REQUEST_PENDING) { + return; + } + + req->status = NT_STATUS_IO_TIMEOUT; + req->state = RPC_REQUEST_DONE; + DLIST_REMOVE(req->p->conn->pending, req); + if (req->async.callback) { + req->async.callback(req); + } +} + /* make sure requests are cleaned up @@ -932,6 +968,12 @@ struct rpc_request *dcerpc_request_send(struct dcerpc_pipe *p, remaining -= chunk; } + if (p->request_timeout) { + event_add_timed(dcerpc_event_context(p), req, + timeval_current_ofs(p->request_timeout, 0), + dcerpc_timeout_handler, req); + } + talloc_set_destructor(req, dcerpc_req_destructor); return req; diff --git a/source4/librpc/rpc/dcerpc.h b/source4/librpc/rpc/dcerpc.h index 89a969a118..2f64c0ef34 100644 --- a/source4/librpc/rpc/dcerpc.h +++ b/source4/librpc/rpc/dcerpc.h @@ -94,8 +94,14 @@ struct dcerpc_pipe { /* the last fault code from a DCERPC fault */ uint32_t last_fault_code; + + /* timeout for individual rpc requests, in seconds */ + uint_t request_timeout; }; +/* default timeout for all rpc requests, in seconds */ +#define DCERPC_REQUEST_TIMEOUT 60 + /* dcerpc pipe flags */ #define DCERPC_DEBUG_PRINT_IN (1<<0) diff --git a/source4/librpc/rpc/dcerpc_util.c b/source4/librpc/rpc/dcerpc_util.c index 949b21e68c..8ae7814c26 100644 --- a/source4/librpc/rpc/dcerpc_util.c +++ b/source4/librpc/rpc/dcerpc_util.c @@ -1343,6 +1343,7 @@ NTSTATUS dcerpc_secondary_context(struct dcerpc_pipe *p, return NT_STATUS_NO_MEMORY; } p2->conn = talloc_reference(p2, p->conn); + p2->request_timeout = p->request_timeout; p2->context_id = ++p->conn->next_context_id; -- cgit