#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;
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);
}
}
l.sl_url.bv_val = NULL;
+ l.sl_is_mute = 0;
#ifndef HAVE_TLS
if( ldap_pvt_url_scheme2tls( lud->lud_scheme ) ) {
{
int l;
time_t last_idle_check = 0;
+ struct timeval idle;
+
+#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;
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;
#ifdef LDAP_SYNCREPL
- struct timeval diff;
struct timeval *cat;
time_t tdelta = 1;
struct re_s* rtask;
#endif
-
now = slap_get_time();
- if( emfile ) {
+ if( ( global_idletimeout > 0 ) &&
+ difftime( last_idle_check +
+ global_idletimeout/SLAPD_IDLE_CHECK_LIMIT, now ) < 0 ) {
connections_timeout_idle( now );
-
- } else if ( global_idletimeout > 0 ) {
- if ( difftime( last_idle_check+global_idletimeout/SLAPD_IDLE_CHECK_LIMIT, now ) < 0 ) {
- connections_timeout_idle( now );
- last_idle_check = now;
- }
+ last_idle_check = now;
}
+ tv = idle;
#ifdef SIGHUP
if( slapd_gentle_shutdown ) {
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 );
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 );
}
#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);
+
+ tvp = at ? &tv : NULL;
#ifdef LDAP_SYNCREPL
ldap_pvt_thread_mutex_lock( &syncrepl_rq.rq_mutex );
ldap_pvt_thread_mutex_unlock( &syncrepl_rq.rq_mutex );
if ( cat != NULL ) {
- diff.tv_sec = difftime( cat->tv_sec, now );
- if ( diff.tv_sec == 0 )
- diff.tv_sec = tdelta;
- }
-#endif
-
-#if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS )
- tvp = NULL;
-#else
- tvp = at ? &zero : NULL;
-#endif
-
-#ifdef LDAP_SYNCREPL
- if ( cat != NULL ) {
- if ( tvp == NULL ) {
- tvp = &diff;
+ time_t diff = difftime( cat->tv_sec, now );
+ if ( diff == 0 )
+ diff = tdelta;
+ if ( tvp == NULL )
+ tvp = &tv;
+ if ( diff < tv.tv_sec ) {
+ tv.tv_sec = diff;
+ tv.tv_usec = 0;
}
}
#endif
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
if ( !FD_ISSET( slap_listeners[l]->sl_sd, &readfds ) )
continue;
-
+
#ifdef LDAP_CONNECTIONLESS
if ( slap_listeners[l]->sl_is_udp ) {
/* The first time we receive a query, we set this
}
#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 */
#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 ) {
#endif
{
ber_socket_t wd;
- int is_listener = 0;
#ifdef HAVE_WINSOCK
wd = writefds.fd_array[i];
#else
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 );
#endif
{
ber_socket_t rd;
- int is_listener = 0;
-
#ifdef HAVE_WINSOCK
rd = readfds.fd_array[i];
#else
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 );