From 24e05d4df2d791ae8f36dcc092915f12b992c3d6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 11 Jun 2007 22:28:27 +0000 Subject: r23424: Thanks to Jerry, we finally tracked down the : winbindd: Exceeding 200 client connections, no idle connection found" bug #3204. This fixes it in Jerry's testing ! Jeremy. (This used to be commit 0c7ce6a68286fa98258828545fc869aaac19a028) --- source3/nsswitch/winbindd_dual.c | 62 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) (limited to 'source3/nsswitch/winbindd_dual.c') diff --git a/source3/nsswitch/winbindd_dual.c b/source3/nsswitch/winbindd_dual.c index 90046572bc..54525f8da1 100644 --- a/source3/nsswitch/winbindd_dual.c +++ b/source3/nsswitch/winbindd_dual.c @@ -96,6 +96,7 @@ struct winbindd_async_request { struct winbindd_request *request; struct winbindd_response *response; void (*continuation)(void *private_data, BOOL success); + struct timed_event *reply_timeout_event; void *private_data; }; @@ -160,8 +161,38 @@ static void async_main_request_sent(void *private_data, BOOL success) async_request_sent, state); } +/**************************************************************** + Handler triggered if the child winbindd doesn't respond within + a given timeout. +****************************************************************/ + +static void async_request_timeout_handler(struct event_context *ctx, + struct timed_event *te, + const struct timeval *now, + void *private_data) +{ + struct winbindd_async_request *state = + talloc_get_type_abort(private_data, struct winbindd_async_request); + + /* Deal with the reply - set to error. */ + + async_reply_recv(private_data, False); + + /* + * Close the socket to the child. Should cause the + * child to exit. + */ + + DEBUG(0,("async_request_timeout_handler: child pid %u is not responding. " + "Closing connection to it.\n", + state->child->pid )); + + winbind_child_died(state->child->pid); +} + static void async_request_sent(void *private_data_data, BOOL success) { + uint32_t timeout = 30; struct winbindd_async_request *state = talloc_get_type_abort(private_data_data, struct winbindd_async_request); @@ -180,6 +211,33 @@ static void async_request_sent(void *private_data_data, BOOL success) &state->response->result, sizeof(state->response->result), async_reply_recv, state); + + /* + * Normal timeouts are 30s, but auth requests may take a long + * time to timeout. + */ + + if (state->request->cmd == WINBINDD_PAM_AUTH || + state->request->cmd == WINBINDD_PAM_AUTH_CRAP ) { + + timeout = 300; + } + + /* + * Set up a timeout of 1 minute for the response. + * If we don't get it close the child socket and + * report failure. + */ + + state->reply_timeout_event = event_add_timed(winbind_event_context(), + NULL, + timeval_current_ofs(timeout,0), + "async_request_timeout", + async_request_timeout_handler, + state); + if (!state->reply_timeout_event) { + smb_panic("async_request_sent: failed to add timeout handler.\n"); + } } static void async_reply_recv(void *private_data, BOOL success) @@ -188,6 +246,10 @@ static void async_reply_recv(void *private_data, BOOL success) talloc_get_type_abort(private_data, struct winbindd_async_request); struct winbindd_child *child = state->child; + if (state->reply_timeout_event) { + TALLOC_FREE(state->reply_timeout_event); + } + state->response->length = sizeof(struct winbindd_response); if (!success) { -- cgit