Author: jra
Date: 2007-06-11 22:28:27 +0000 (Mon, 11 Jun 2007)
New Revision: 23424

WebSVN: 
http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=23424

Log:
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.

Modified:
   branches/SAMBA_3_0/source/nsswitch/winbindd_dual.c
   branches/SAMBA_3_0_26/source/nsswitch/winbindd_dual.c


Changeset:
Modified: branches/SAMBA_3_0/source/nsswitch/winbindd_dual.c
===================================================================
--- branches/SAMBA_3_0/source/nsswitch/winbindd_dual.c  2007-06-11 20:56:17 UTC 
(rev 23423)
+++ branches/SAMBA_3_0/source/nsswitch/winbindd_dual.c  2007-06-11 22:28:27 UTC 
(rev 23424)
@@ -96,6 +96,7 @@
        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 @@
                          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 @@
                         &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 @@
                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) {

Modified: branches/SAMBA_3_0_26/source/nsswitch/winbindd_dual.c
===================================================================
--- branches/SAMBA_3_0_26/source/nsswitch/winbindd_dual.c       2007-06-11 
20:56:17 UTC (rev 23423)
+++ branches/SAMBA_3_0_26/source/nsswitch/winbindd_dual.c       2007-06-11 
22:28:27 UTC (rev 23424)
@@ -96,6 +96,7 @@
        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 @@
                          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 @@
                         &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 @@
                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) {

Reply via email to