#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;
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;
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 ) {
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);
-#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
}
}
#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 */
{
/* 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,
#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 );