r1588: This is one of the more pathetic patches I ever checked in. Many hours of
authorVolker Lendecke <vlendec@samba.org>
Mon, 26 Jul 2004 07:41:16 +0000 (07:41 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 15:52:16 +0000 (10:52 -0500)
coding have passed, but I could not find a way to get the OpenLDAP libraries
to reliably time out on any of the queries we make, *and* get correct error
returns. No, async calls and ldap_result does NOT work, or I was simply too
stupid to correctly interpret the OpenLDAP manpage and source.

We can not allow to hang indefinitely in an ldap query, especially not for
winbindd. "ldap timeout" now specifies the overall timeout for the complete
operation, that's why I increased that to 15 seconds.

Volker

source/include/smbldap.h
source/lib/smbldap.c

index b94577178b34d191500bfb696bebb4b2aae1ed28..6046af464e6a966aab836d2efa47a3de36878c70 100644 (file)
@@ -154,6 +154,6 @@ struct smbldap_state {
 
 struct smbldap_state;
 
-#define LDAP_CONNECT_DEFAULT_TIMEOUT   5
+#define LDAP_CONNECT_DEFAULT_TIMEOUT   15
 
 #endif /* _SMBLDAP_H */
index a1a3117d8854b0581f19d77cdc0471ee7a7bc834..0980b763adbc63bb1fd1ce022ca165907c8d2fcb 100644 (file)
@@ -879,37 +879,69 @@ static NTSTATUS smbldap_close(struct smbldap_state *ldap_state)
        return NT_STATUS_OK;
 }
 
-int smbldap_retry_open(struct smbldap_state *ldap_state, int *attempts)
+static BOOL got_alarm;
+
+static void (*old_handler)(int);
+
+static void gotalarm_sig(int dummy)
 {
-       int rc;
+       got_alarm = True;
+}
 
-       SMB_ASSERT(ldap_state && attempts);
-               
-       if (*attempts != 0) {
-               unsigned int sleep_time;
-               uint8 rand_byte;
-
-               /* Sleep for a random timeout */
-               rand_byte = (char)(sys_random());
-
-               sleep_time = (((*attempts)*(*attempts))/2)*rand_byte*2; 
-               /* we retry after (0.5, 1, 2, 3, 4.5, 6) seconds
-                  on average.  
-                */
-               DEBUG(3, ("Sleeping for %u milliseconds before reconnecting\n", 
-                         sleep_time));
-               smb_msleep(sleep_time);
+static int another_ldap_try(struct smbldap_state *ldap_state, int *rc,
+                           int *attempts, time_t endtime)
+{
+       time_t now = time(NULL);
+       int open_rc = LDAP_SERVER_DOWN;
+
+       if (*rc != LDAP_SERVER_DOWN)
+               goto no_next;
+
+       now = time(NULL);
+
+       if (now >= endtime) {
+               smbldap_close(ldap_state);
+               *rc = LDAP_TIMEOUT;
+               goto no_next;
        }
-       (*attempts)++;
 
-       if ((rc = smbldap_open(ldap_state))) {
-               DEBUG(1,("Connection to LDAP Server failed for the %d try!\n",*attempts));
-               return rc;
-       } 
-       
-       return LDAP_SUCCESS;            
-}
+       if (*attempts == 0) {
+               got_alarm = False;
+               old_handler = CatchSignal(SIGALRM, gotalarm_sig);
+               alarm(endtime - now);
+       }
+
+       while (1) {
+
+               if (*attempts != 0)
+                       smb_msleep(1000);
 
+               *attempts += 1;
+
+               open_rc = smbldap_open(ldap_state);
+
+               if (open_rc == LDAP_SUCCESS) {
+                       ldap_state->last_use = now;
+                       return True;
+               }
+
+               if (got_alarm) {
+                       *rc = LDAP_TIMEOUT;
+                       break;
+               }
+
+               if (open_rc != LDAP_SUCCESS) {
+                       DEBUG(1, ("Connection to LDAP server failed for the "
+                                 "%d try!\n", *attempts));
+               }
+       }
+
+ no_next:
+       CatchSignal(SIGALRM, old_handler);
+       alarm(0);
+       ldap_state->last_use = now;
+       return False;
+}
 
 /*********************************************************************
  ********************************************************************/
@@ -922,6 +954,7 @@ int smbldap_search(struct smbldap_state *ldap_state,
        int             rc = LDAP_SERVER_DOWN;
        int             attempts = 0;
        char           *utf8_filter;
+       time_t          endtime = time(NULL)+lp_ldap_timeout();
 
        SMB_ASSERT(ldap_state);
        
@@ -955,22 +988,10 @@ int smbldap_search(struct smbldap_state *ldap_state,
                return LDAP_NO_MEMORY;
        }
 
-       while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) {
-               
-               if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
-                       continue;
-               
+       while (another_ldap_try(ldap_state, &rc, &attempts, endtime))
                rc = ldap_search_s(ldap_state->ldap_struct, base, scope, 
                                   utf8_filter, attrs, attrsonly, res);
-       }
        
-       if (rc == LDAP_SERVER_DOWN) {
-               DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
-               smbldap_close(ldap_state);      
-       }
-
-       ldap_state->last_use = time(NULL);
-
        SAFE_FREE(utf8_filter);
        return rc;
 }
@@ -980,6 +1001,7 @@ int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *at
        int             rc = LDAP_SERVER_DOWN;
        int             attempts = 0;
        char           *utf8_dn;
+       time_t          endtime = time(NULL)+lp_ldap_timeout();
 
        SMB_ASSERT(ldap_state);
 
@@ -989,21 +1011,9 @@ int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *at
                return LDAP_NO_MEMORY;
        }
 
-       while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) {
-               
-               if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
-                       continue;
-               
+       while (another_ldap_try(ldap_state, &rc, &attempts, endtime))
                rc = ldap_modify_s(ldap_state->ldap_struct, utf8_dn, attrs);
-       }
-       
-       if (rc == LDAP_SERVER_DOWN) {
-               DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
-               smbldap_close(ldap_state);      
-       }
-       
-       ldap_state->last_use = time(NULL);
-
+               
        SAFE_FREE(utf8_dn);
        return rc;
 }
@@ -1013,6 +1023,7 @@ int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs
        int             rc = LDAP_SERVER_DOWN;
        int             attempts = 0;
        char           *utf8_dn;
+       time_t          endtime = time(NULL)+lp_ldap_timeout();
        
        SMB_ASSERT(ldap_state);
 
@@ -1022,21 +1033,9 @@ int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs
                return LDAP_NO_MEMORY;
        }
 
-       while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) {
-               
-               if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
-                       continue;
-               
+       while (another_ldap_try(ldap_state, &rc, &attempts, endtime))
                rc = ldap_add_s(ldap_state->ldap_struct, utf8_dn, attrs);
-       }
        
-       if (rc == LDAP_SERVER_DOWN) {
-               DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
-               smbldap_close(ldap_state);      
-       }
-               
-       ldap_state->last_use = time(NULL);
-
        SAFE_FREE(utf8_dn);
        return rc;
 }
@@ -1046,6 +1045,7 @@ int smbldap_delete(struct smbldap_state *ldap_state, const char *dn)
        int             rc = LDAP_SERVER_DOWN;
        int             attempts = 0;
        char           *utf8_dn;
+       time_t          endtime = time(NULL)+lp_ldap_timeout();
        
        SMB_ASSERT(ldap_state);
 
@@ -1055,21 +1055,9 @@ int smbldap_delete(struct smbldap_state *ldap_state, const char *dn)
                return LDAP_NO_MEMORY;
        }
 
-       while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) {
-               
-               if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
-                       continue;
-               
+       while (another_ldap_try(ldap_state, &rc, &attempts, endtime))
                rc = ldap_delete_s(ldap_state->ldap_struct, utf8_dn);
-       }
        
-       if (rc == LDAP_SERVER_DOWN) {
-               DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
-               smbldap_close(ldap_state);      
-       }
-               
-       ldap_state->last_use = time(NULL);
-
        SAFE_FREE(utf8_dn);
        return rc;
 }
@@ -1081,26 +1069,15 @@ int smbldap_extended_operation(struct smbldap_state *ldap_state,
 {
        int             rc = LDAP_SERVER_DOWN;
        int             attempts = 0;
+       time_t          endtime = time(NULL)+lp_ldap_timeout();
        
        if (!ldap_state)
                return (-1);
 
-       while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) {
-               
-               if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
-                       continue;
-               
-               rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid, reqdata, 
-                                              serverctrls, clientctrls, retoidp, retdatap);
-       }
-       
-       if (rc == LDAP_SERVER_DOWN) {
-               DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
-               smbldap_close(ldap_state);      
-       }
-               
-       ldap_state->last_use = time(NULL);
-
+       while (another_ldap_try(ldap_state, &rc, &attempts, endtime))
+               rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid,
+                                              reqdata, serverctrls,
+                                              clientctrls, retoidp, retdatap);
        return rc;
 }