]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
Import ITS#2482, ITS#2374 from HEAD
authorHoward Chu <hyc@openldap.org>
Fri, 16 May 2003 02:38:09 +0000 (02:38 +0000)
committerHoward Chu <hyc@openldap.org>
Fri, 16 May 2003 02:38:09 +0000 (02:38 +0000)
CHANGES
servers/slapd/daemon.c
servers/slapd/slap.h

diff --git a/CHANGES b/CHANGES
index 72fca49c91bf5f5ea91148c8ed6a3f735ba362ae..d1f9089c68582b26f63daad5aaa51df0ce00f00d 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,8 @@
 OpenLDAP 2.1 Change Log
 
 OpenLDAP 2.1.20 Engineering
+       Fixed slapd idletimeout behavior (ITS#2374)
+       Fixed slapd accept() fail busyloop (ITS#2482)
        Fixed slapd regex lookup mutex issue (ITS#2505)
        Fixed back-bdb/ldbm filter indexing bugs (ITS#2506) (ITS#2507)
        Fixed back-bdb cache consistency bug (ITS#2470)
index 2d0d93793a87e295cec98a3da7f85d9d139f32cf..71e7c0719161b6195aed55d66130e86d44779d2b 100644 (file)
@@ -51,6 +51,7 @@ Listener **slap_listeners = NULL;
 #define SLAPD_LISTEN 10
 
 static ber_socket_t wake_sds[2];
+static int emfile;
 
 #if defined(NO_THREADS) || defined(HAVE_GNU_PTH)
 static int waking;
@@ -247,6 +248,28 @@ void slapd_remove(ber_socket_t s, int wake) {
        FD_CLR( s, &slap_daemon.sd_readers );
        FD_CLR( s, &slap_daemon.sd_writers );
 
+       /* If we ran out of file descriptors, we dropped a listener from
+        * the select() loop. Now that we're removing a session from our
+        * control, we can try to resume a dropped listener to use.
+        */
+       if ( emfile ) {
+               int i;
+               for ( i = 0; slap_listeners[i] != NULL; i++ ) {
+                       if ( slap_listeners[i]->sl_sd != AC_SOCKET_INVALID ) {
+                               if ( slap_listeners[i]->sl_sd == s ) continue;
+                               if ( slap_listeners[i]->sl_is_mute ) {
+                                       slap_listeners[i]->sl_is_mute = 0;
+                                       emfile--;
+                                       break;
+                               }
+                       }
+               }
+               /* Walked the entire list without enabling anything; emfile
+                * counter is stale. Reset it.
+                */
+               if ( slap_listeners[i] == NULL )
+                       emfile = 0;
+       }
        ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
        WAKE_LISTENER(wake || slapd_gentle_shutdown == 2);
 }
@@ -617,6 +640,7 @@ static int slap_open_listener(
        }
 
        l.sl_url.bv_val = NULL;
+       l.sl_is_mute = 0;
 
 #ifndef HAVE_TLS
        if( ldap_pvt_url_scheme2tls( lud->lud_scheme ) ) {
@@ -1109,11 +1133,25 @@ slapd_daemon_task(
 {
        int l;
        time_t  last_idle_check = 0;
+       struct timeval idle;
        time( &starttime );
 
+#define SLAPD_IDLE_CHECK_LIMIT 4
+
        if ( global_idletimeout > 0 ) {
                last_idle_check = slap_get_time();
+               /* Set the select timeout.
+                * Don't just truncate, preserve the fractions of
+                * seconds to prevent sleeping for zero time.
+                */
+               idle.tv_sec = global_idletimeout/SLAPD_IDLE_CHECK_LIMIT;
+               idle.tv_usec = global_idletimeout - idle.tv_sec * SLAPD_IDLE_CHECK_LIMIT;
+               idle.tv_usec *= 1000000 / SLAPD_IDLE_CHECK_LIMIT;
+       } else {
+               idle.tv_sec = 0;
+               idle.tv_usec = 0;
        }
+
        for ( l = 0; slap_listeners[l] != NULL; l++ ) {
                if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
                        continue;
@@ -1197,29 +1235,25 @@ slapd_daemon_task(
                ber_socket_t nfds;
 #define SLAPD_EBADF_LIMIT 16
                int ebadf = 0;
-               int emfile = 0;
 
-#define SLAPD_IDLE_CHECK_LIMIT 4
                time_t  now;
 
-
                fd_set                  readfds;
                fd_set                  writefds;
                Sockaddr                from;
 
-               struct timeval          zero;
+               struct timeval          tv;
                struct timeval          *tvp;
 
-               if( emfile ) {
-                       now = slap_get_time();
+               now = slap_get_time();
+
+               if( ( global_idletimeout > 0 ) &&
+                       difftime( last_idle_check +
+                       global_idletimeout/SLAPD_IDLE_CHECK_LIMIT, now ) < 0 ) {
                        connections_timeout_idle( now );
+                       last_idle_check = now;
                }
-               else if ( global_idletimeout > 0 ) {
-                       now = slap_get_time();
-                       if ( difftime( last_idle_check+global_idletimeout/SLAPD_IDLE_CHECK_LIMIT, now ) < 0 ) {
-                               connections_timeout_idle( now );
-                       }
-               }
+               tv = idle;
 
 #ifdef SIGHUP
                if( slapd_gentle_shutdown ) {
@@ -1245,8 +1279,7 @@ slapd_daemon_task(
                FD_ZERO( &writefds );
                FD_ZERO( &readfds );
 
-               zero.tv_sec = 0;
-               zero.tv_usec = 0;
+               at = 0;
 
                ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
 
@@ -1269,6 +1302,9 @@ slapd_daemon_task(
                for ( l = 0; slap_listeners[l] != NULL; l++ ) {
                        if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
                                continue;
+                       if ( slap_listeners[l]->sl_is_mute )
+                               FD_CLR( slap_listeners[l]->sl_sd, &readfds );
+                       else
                        if (!FD_ISSET(slap_listeners[l]->sl_sd, &readfds))
                            FD_SET( slap_listeners[l]->sl_sd, &readfds );
                }
@@ -1278,31 +1314,31 @@ slapd_daemon_task(
 #else
                nfds = dtblsize;
 #endif
+               if ( global_idletimeout && slap_daemon.sd_nactives )
+                       at = 1;
 
                ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
 
-               at = ldap_pvt_thread_pool_backload(&connection_pool);
+               if ( !at )
+                       at = ldap_pvt_thread_pool_backload(&connection_pool);
 
-#if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS )
-               tvp = NULL;
-#else
-               tvp = at ? &zero : NULL;
-#endif
+               tvp = at ? &tv : NULL;
 
                for ( l = 0; slap_listeners[l] != NULL; l++ ) {
-                       if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
+                       if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID ||
+                           slap_listeners[l]->sl_is_mute )
                                continue;
 
 #ifdef NEW_LOGGING
                        LDAP_LOG( CONNECTION, DETAIL1, 
                                "slapd_daemon_task: select: listen=%d "
                                "active_threads=%d tvp=%s\n",
-                               slap_listeners[l]->sl_sd, at, tvp == NULL ? "NULL" : "zero" );
+                               slap_listeners[l]->sl_sd, at, tvp == NULL ? "NULL" : "idle" );
 #else
                        Debug( LDAP_DEBUG_CONNS,
                                "daemon: select: listen=%d active_threads=%d tvp=%s\n",
                                        slap_listeners[l]->sl_sd, at,
-                                       tvp == NULL ? "NULL" : "zero" );
+                                       tvp == NULL ? "NULL" : "idle" );
 #endif
                }
 
@@ -1423,50 +1459,45 @@ slapd_daemon_task(
                        }
 #endif
 
+                       /* Don't need to look at this in the data loops */
+                       FD_CLR( slap_listeners[l]->sl_sd, &readfds );
+                       FD_CLR( slap_listeners[l]->sl_sd, &writefds );
+
                        s = accept( slap_listeners[l]->sl_sd,
                                (struct sockaddr *) &from, &len );
                        if ( s == AC_SOCKET_INVALID ) {
                                int err = sock_errno();
 
+                               if(
 #ifdef EMFILE
-                               if( err == EMFILE ) {
-                                       emfile++;
-                               } else
+                                   err == EMFILE ||
 #endif
 #ifdef ENFILE
-                               if( err == ENFILE ) {
-                                       emfile++;
-                               } else 
+                                   err == ENFILE ||
 #endif
+                                   0 )
                                {
-                                       emfile=0;
+                                       ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
+                                       emfile++;
+                                       /* Stop listening until an existing session closes */
+                                       slap_listeners[l]->sl_is_mute = 1;
+                                       ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
                                }
 
-                               if( emfile < 3 ) {
 #ifdef NEW_LOGGING
-                                       LDAP_LOG( CONNECTION, ERR, 
-                                               "slapd_daemon_task: accept(%ld) failed errno=%d (%s)\n",
-                                               (long)slap_listeners[l]->sl_sd, 
-                                               err, sock_errstr(err) );
+                               LDAP_LOG( CONNECTION, ERR, 
+                                       "slapd_daemon_task: accept(%ld) failed errno=%d (%s)\n",
+                                       (long)slap_listeners[l]->sl_sd, 
+                                       err, sock_errstr(err) );
 #else
-                                       Debug( LDAP_DEBUG_ANY,
-                                           "daemon: accept(%ld) failed errno=%d (%s)\n",
-                                           (long) slap_listeners[l]->sl_sd, err,
-                                           sock_errstr(err) );
-#endif
-                               } else {
-                                       /* prevent busy loop */
-#  ifdef HAVE_USLEEP
-                                       if( emfile % 4 == 3 ) usleep( 250 );
-#  else
-                                       if( emfile % 8 == 7 ) sleep( 1 );
-#  endif
-                               }
-
+                               Debug( LDAP_DEBUG_ANY,
+                                       "daemon: accept(%ld) failed errno=%d (%s)\n",
+                                       (long) slap_listeners[l]->sl_sd, err,
+                                       sock_errstr(err) );
+#endif
                                ldap_pvt_thread_yield();
                                continue;
                        }
-                       emfile = 0;
 
 #ifndef HAVE_WINSOCK
                        /* make sure descriptor number isn't too great */
@@ -1635,7 +1666,7 @@ slapd_daemon_task(
                                {
                                        /* DENY ACCESS */
                                        Statslog( LDAP_DEBUG_STATS,
-                                               "fd=%ld DENIED from %s (%s)",
+                                               "fd=%ld DENIED from %s (%s)\n",
                                                (long) s,
                                                dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN,
                                                peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN,
@@ -1721,23 +1752,7 @@ slapd_daemon_task(
 #else
                for ( i = 0; i < nfds; i++ ) {
                        int     r, w;
-                       int     is_listener = 0;
 
-                       for ( l = 0; slap_listeners[l] != NULL; l++ ) {
-                               if ( i == slap_listeners[l]->sl_sd ) {
-#ifdef LDAP_CONNECTIONLESS
-                               /* The listener is the data port. Don't
-                                * skip it.
-                                */
-                                       if (slap_listeners[l]->sl_is_udp) continue;
-#endif
-                                       is_listener = 1;
-                                       break;
-                               }
-                       }
-                       if ( is_listener ) {
-                               continue;
-                       }
                        r = FD_ISSET( i, &readfds );
                        w = FD_ISSET( i, &writefds );
                        if ( r || w ) {
@@ -1767,7 +1782,6 @@ slapd_daemon_task(
 #endif
                {
                        ber_socket_t wd;
-                       int is_listener = 0;
 #ifdef HAVE_WINSOCK
                        wd = writefds.fd_array[i];
 #else
@@ -1777,18 +1791,6 @@ slapd_daemon_task(
                        wd = i;
 #endif
 
-                       for ( l = 0; slap_listeners[l] != NULL; l++ ) {
-                               if ( i == slap_listeners[l]->sl_sd ) {
-#ifdef LDAP_CONNECTIONLESS
-                                       if (slap_listeners[l]->sl_is_udp) continue;
-#endif
-                                       is_listener = 1;
-                                       break;
-                               }
-                       }
-                       if ( is_listener ) {
-                               continue;
-                       }
 #ifdef NEW_LOGGING
                        LDAP_LOG( CONNECTION, DETAIL2, 
                                "slapd_daemon_task: write active on %d\n", wd, 0, 0 );
@@ -1817,8 +1819,6 @@ slapd_daemon_task(
 #endif
                {
                        ber_socket_t rd;
-                       int is_listener = 0;
-
 #ifdef HAVE_WINSOCK
                        rd = readfds.fd_array[i];
 #else
@@ -1828,19 +1828,6 @@ slapd_daemon_task(
                        rd = i;
 #endif
 
-                       for ( l = 0; slap_listeners[l] != NULL; l++ ) {
-                               if ( rd == slap_listeners[l]->sl_sd ) {
-#ifdef LDAP_CONNECTIONLESS
-                                       if (slap_listeners[l]->sl_is_udp) continue;
-#endif
-                                       is_listener = 1;
-                                       break;
-                               }
-                       }
-                       if ( is_listener ) {
-                               continue;
-                       }
-
 #ifdef NEW_LOGGING
                        LDAP_LOG( CONNECTION, DETAIL2, 
                                "slapd_daemon_task: read activity on %d\n", rd, 0, 0 );
index 1bc94e0e16d05449efcdf481f01bd80caa35fa99..6b47daaa0936a9bf7ece25e3b5749ffd61245ad2 100644 (file)
@@ -1995,6 +1995,7 @@ struct slap_listener {
 #ifdef LDAP_CONNECTIONLESS
        int     sl_is_udp;              /* UDP listener is also data port */
 #endif
+       int     sl_is_mute;     /* Listening is temporarily disabled */
        ber_socket_t sl_sd;
        Sockaddr sl_sa;
 #define sl_addr        sl_sa.sa_in_addr