r7497: add timeouts to all rpc requests. The default timeout is 60
authorAndrew Tridgell <tridge@samba.org>
Sun, 12 Jun 2005 02:42:40 +0000 (02:42 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:18:00 +0000 (13:18 -0500)
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
source4/librpc/rpc/dcerpc.h
source4/librpc/rpc/dcerpc_util.c

index 284a3c884148d5c771c025702d6167a57813e64d..fa7fe728d44365f811c07efc9d2d9fdd634c7fbc 100644 (file)
@@ -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;
index 89a969a118da24c5e8325da92647e8087ae15e28..2f64c0ef3407cb6e96a48b9285c1747c59c3742f 100644 (file)
@@ -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)
index 949b21e68c4e34e223505d3ed82102aba83b2c47..8ae7814c2658e5d69f860603df2dd5f516a9e0a3 100644 (file)
@@ -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;