]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/daemon.c
document option '-F'
[openldap] / servers / slapd / daemon.c
index 5cc423dc98f74a68e88ed7c6c72a08686603fb8f..2893a905f90c1f05de7eb85f2332dd0cd2605439 100644 (file)
@@ -1,7 +1,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 1998-2004 The OpenLDAP Foundation.
+ * Copyright 1998-2005 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 
 #include "ldap_rq.h"
 
+#undef HAVE_EPOLL
+
+#if defined(HAVE_SYS_EPOLL_H) && defined(HAVE_EPOLL)
+#include <sys/epoll.h>
+#endif
+
 #ifdef HAVE_TCPD
 #include <tcpd.h>
 #define SLAP_STRING_UNKNOWN    STRING_UNKNOWN
@@ -66,6 +72,7 @@ int slap_inet4or6 = AF_INET;
 time_t starttime;
 ber_socket_t dtblsize;
 slap_ssf_t local_ssf = LDAP_PVT_SASL_LOCAL_SSF;
+struct runqueue_s slapd_rq;
 
 Listener **slap_listeners = NULL;
 
@@ -76,7 +83,7 @@ static int emfile;
 
 static int waking;
 #define WAKE_LISTENER(w) \
-do { if (w && waking < 5) { tcp_write( wake_sds[1], "0", 1 ); waking++;} } while(0)
+do { if (w && waking < 5) { waking++; tcp_write( wake_sds[1], "0", 1 ); } } while(0)
 
 volatile sig_atomic_t slapd_shutdown = 0, slapd_gentle_shutdown = 0;
 volatile sig_atomic_t slapd_abrupt_shutdown = 0;
@@ -109,81 +116,101 @@ static struct slap_daemon {
 
 #ifdef HAVE_EPOLL
 #define        SLAP_EVENTS_ARE_INDEXED 0
-#define        SLAP_SOCK_IX(fd)        (slap_daemon.sd_index[fd])
-#define SLAP_SOCK_EP(fd)       (slap_daemon.sd_epolls[SLAP_SOCK_IX(fd)])
-#define SLAP_SOCK_FD(fd)       (SLAP_SOCK_EP(fd).data.fd)
-#define SLAP_SOCK_EV(fd)       (SLAP_SOCK_EP(fd).events)
-#define SLAP_SOCK_IS_ACTIVE(fd)        (SLAP_SOCK_IX(fd) != -1 && SLAP_SOCK_FD(fd) == fd)
-#define SLAP_SOCK_NOT_ACTIVE(fd)       (SLAP_SOCK_IX(fd) == -1)
-#define SLAP_SOCK_IS_SET(fd, mode)     (SLAP_SOCK_EV(fd) & mode)
-
-#define SLAP_SOCK_IS_READ(fd)  SLAP_SOCK_IS_SET(fd, EPOLLIN)
-#define SLAP_SOCK_IS_WRITE(fd) SLAP_SOCK_IS_SET(fd, EPOLLOUT)
-
-#define        SLAP_SET_SOCK(fd, events) do { \
-       assert(SLAP_SOCK_IS_ACTIVE(fd));        \
-       if ((SLAP_SOCK_EV(fd) & events) != events) {    \
-               SLAP_SOCK_EV(fd) |= events;     \
-               rc = epoll_ctl(slap_daemon.sd_epfd, EPOLL_CTL_MOD, fd,  \
-                       &SLAP_SOCK_EP(fd));     \
+#define        SLAP_SOCK_IX(s) (slap_daemon.sd_index[s])
+#define SLAP_SOCK_EP(s)        (slap_daemon.sd_epolls[SLAP_SOCK_IX(s)])
+#define SLAP_SOCK_EV(s)        (SLAP_SOCK_EP(s).events)
+#define SLAP_SOCK_IS_ACTIVE(s) (SLAP_SOCK_IX(s) != -1)
+#define SLAP_SOCK_NOT_ACTIVE(s)        (SLAP_SOCK_IX(s) == -1)
+#define SLAP_SOCK_IS_SET(s, mode)      (SLAP_SOCK_EV(s) & mode)
+
+#define SLAP_SOCK_IS_READ(s)   SLAP_SOCK_IS_SET(s, EPOLLIN)
+#define SLAP_SOCK_IS_WRITE(s)  SLAP_SOCK_IS_SET(s, EPOLLOUT)
+
+#define        SLAP_SET_SOCK(s, mode) do { \
+       if ((SLAP_SOCK_EV(s) & mode) != mode) { \
+               SLAP_SOCK_EV(s) |= mode;        \
+               epoll_ctl(slap_daemon.sd_epfd, EPOLL_CTL_MOD, s,        \
+                       &SLAP_SOCK_EP(s));      \
        }       \
 } while(0)
 
-#define SLAP_CLR_SOCK(fd, events) do { \
-       assert(SLAP_SOCK_IS_ACTIVE(fd));        \
-       if ((SLAP_SOCK_EV(fd) & events)) { \
-               SLAP_SOCK_EV(fd) &= ~events;    \
-               rc = epoll_ctl(slap_daemon.sd_epfd, EPOLL_CTL_MOD, fd,  \
-                       &SLAP_SOCK_EP(fd));     \
+#define SLAP_CLR_SOCK(s, mode) do { \
+       if ((SLAP_SOCK_EV(s) & mode)) { \
+               SLAP_SOCK_EV(s) &= ~mode;       \
+               epoll_ctl(slap_daemon.sd_epfd, EPOLL_CTL_MOD, s,        \
+                       &SLAP_SOCK_EP(s));      \
        }       \
-} while(0)     \
-
-#define SLAP_SOCK_SET_READ(fd) SLAP_SET_SOCK(fd, EPOLLIN)
-#define SLAP_SOCK_SET_WRITE(fd)        SLAP_SET_SOCK(fd, EPOLLOUT)
-
-#define SLAP_SOCK_CLR_READ(fd) SLAP_CLR_SOCK(fd, EPOLLIN)
-#define SLAP_SOCK_CLR_WRITE(fd)        SLAP_CLR_SOCK(fd, EPOLLOUT)
+} while(0)
 
-#define SLAP_CLR_EVENT(i, events)      (revents[i].events &= ~events)
+#define SLAP_SOCK_SET_READ(s)  SLAP_SET_SOCK(s, EPOLLIN)
+#define SLAP_SOCK_SET_WRITE(s) SLAP_SET_SOCK(s, EPOLLOUT)
 
-#define SLAP_EVENT_CLR_READ(i) SLAP_CLR_EVENT(i, EPOLLIN)
-#define SLAP_EVENT_CLR_WRITE(i)        SLAP_CLR_EVENT(i, EPOLLOUT)
+#define SLAP_SOCK_CLR_READ(s)  SLAP_CLR_SOCK(s, EPOLLIN)
+#define SLAP_SOCK_CLR_WRITE(s) SLAP_CLR_SOCK(s, EPOLLOUT)
 
-#define SLAP_CHK_EVENT(i, events)      (revents[i].events & events)
+#define SLAP_CLR_EVENT(i, mode)        (revents[i].events &= ~mode)
 
-#define SLAP_EVENT_IS_READ(i)  SLAP_CHK_EVENT(i, EPOLLIN)
-#define SLAP_EVENT_IS_WRITE(i) SLAP_CHK_EVENT(i, EPOLLOUT)
 
-#define SLAP_EVENT_FD(i)       (revents[i].data.fd)
+#define SLAP_EVENT_MAX slap_daemon.sd_nfds
 
-#define SLAP_ADD_SOCK(fd) do { \
-       SLAP_SOCK_IX(fd) = slap_daemon.sd_nfds; \
-       SLAP_SOCK_FD(fd) = fd;  \
-       SLAP_SOCK_EV(fd) = EPOLLIN;     \
-       rc = epoll_ctl(slap_daemon.sd_epfd, EPOLL_CTL_ADD, fd,  \
-                       &SLAP_SOCK_EP(fd));     \
+/* If a Listener address is provided, store that as the epoll data.
+ * Otherwise, store the address of this socket's slot in the
+ * index array. If we can't do this add, the system is out of
+ * resources and we need to shutdown.
+ */
+#define SLAP_ADD_SOCK(s, l) do { \
+       int rc; \
+       SLAP_SOCK_IX(s) = slap_daemon.sd_nfds;  \
+       SLAP_SOCK_EP(s).data.ptr = (l) ? (l) : (void *)(&SLAP_SOCK_IX(s)); \
+       SLAP_SOCK_EV(s) = EPOLLIN;      \
+       rc = epoll_ctl(slap_daemon.sd_epfd, EPOLL_CTL_ADD, s,   \
+                       &SLAP_SOCK_EP(s));      \
        if ( rc == 0 ) slap_daemon.sd_nfds++;   \
+       else {  \
+               Debug( LDAP_DEBUG_ANY, "daemon: epoll_ctl ADD failed, errno %d, shutting down\n",       \
+               errno, 0, 0 );  \
+               slapd_shutdown = 2;     \
+       }       \
 } while(0)
 
-#define SLAP_DEL_SOCK(fd) do { \
-       int index = SLAP_SOCK_IX(fd);
-       
-       rc = epoll_ctl(slap_daemon.sd_epfd, EPOLL_CTL_DEL, fd,  \
-                       &SLAP_SOCK_EP(fd));     \
+#define        SLAP_EV_LISTENER(ptr) (((int *)(ptr) >= slap_daemon.sd_index && \
+        (int *)(ptr) <= (slap_daemon.sd_index+dtblsize)) ? 0 : 1)
+
+#define        SLAP_EV_PTRFD(ptr) (SLAP_EV_LISTENER(ptr) ? \
+        ((Listener *)ptr)->sl_sd : (int *)(ptr) - slap_daemon.sd_index)
+
+#define SLAP_DEL_SOCK(s) do { \
+       int fd, rc, index = SLAP_SOCK_IX(s); \
+       rc = epoll_ctl(slap_daemon.sd_epfd, EPOLL_CTL_DEL, s,   \
+                       &SLAP_SOCK_EP(s));      \
        slap_daemon.sd_epolls[index] = slap_daemon.sd_epolls[slap_daemon.sd_nfds-1];    \
-       slap_daemon.sd_index[slap_daemon.sd_epools[index].data.fd] = index;     \
-       slap_daemon.sd_index[fd] = -1;  \
+       fd = SLAP_EV_PTRFD(slap_daemon.sd_epolls[index].data.ptr);      \
+       slap_daemon.sd_index[fd] = index;       \
+       slap_daemon.sd_index[s] = -1;   \
        slap_daemon.sd_nfds--;  \
 } while(0)
 
-#define        SLAP_SOCK_SET_MUTE(fd)  SLAP_SOCK_CLR_READ(fd)
-#define        SLAP_SOCK_CLR_MUTE(fd)  SLAP_SOCK_SET_READ(fd)
-#define        SLAP_SOCK_IS_MUTE(fd)   !SLAP_SOCK_IS_READ(fd)
+#define SLAP_EVENT_CLR_READ(i) SLAP_CLR_EVENT(i, EPOLLIN)
+#define SLAP_EVENT_CLR_WRITE(i)        SLAP_CLR_EVENT(i, EPOLLOUT)
+
+#define SLAP_CHK_EVENT(i, mode)        (revents[i].events & mode)
+
+#define SLAP_EVENT_IS_READ(i)  SLAP_CHK_EVENT(i, EPOLLIN)
+#define SLAP_EVENT_IS_WRITE(i) SLAP_CHK_EVENT(i, EPOLLOUT)
+#define SLAP_EVENT_IS_LISTENER(i)      SLAP_EV_LISTENER(revents[i].data.ptr)
+#define SLAP_EVENT_LISTENER(i) (revents[i].data.ptr)
+
+#define SLAP_EVENT_FD(i)       SLAP_EV_PTRFD(revents[i].data.ptr)
+#define        SLAP_SOCK_SET_MUTE(s)   SLAP_SOCK_CLR_READ(s)
+#define        SLAP_SOCK_CLR_MUTE(s)   SLAP_SOCK_SET_READ(s)
+#define        SLAP_SOCK_IS_MUTE(s)    !SLAP_SOCK_IS_READ(s)
 
 #define SLAP_SOCK_SET_INIT     \
        slap_daemon.sd_epolls = ch_malloc(sizeof(struct epoll_event) * dtblsize * 2);   \
        slap_daemon.sd_index = ch_malloc(sizeof(int) * dtblsize);       \
-       slap_daemon.sd_epfd = epoll_create( dtblsize )
+       slap_daemon.sd_epfd = epoll_create( dtblsize ); \
+       for (i=0; i<dtblsize; i++) slap_daemon.sd_index[i] = -1
+
 
 #define        SLAP_EVENT_DECL \
        struct epoll_event *revents
@@ -204,7 +231,7 @@ static struct slap_daemon {
 #define SLAP_EVENT_INIT \
        AC_MEMCPY( &readfds, &slap_daemon.sd_readers, sizeof(fd_set) ); \
        if ( nwriters ) \
-               AC_MEMCPY( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) );
+               AC_MEMCPY( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) )
 
 #ifdef FD_SETSIZE
 #define        CHK_SETSIZE     \
@@ -235,19 +262,19 @@ static struct slap_daemon {
 } while(0)
 
 #define SLAP_ADDTEST(s)
-#define SLAP_MAXWAIT   dtblsize
+#define SLAP_EVENT_MAX dtblsize
 #else
 #define SLAP_SOCK_SET_READ(fd) FD_SET(fd, &slap_daemon.sd_readers)
 #define SLAP_SOCK_SET_WRITE(fd)        FD_SET(fd, &slap_daemon.sd_writers)
 
-#define SLAP_MAXWAIT   slap_daemon.sd_nfds
+#define SLAP_EVENT_MAX slap_daemon.sd_nfds
 #define        SLAP_ADDTEST(s) if (s >= slap_daemon.sd_nfds) slap_daemon.sd_nfds = s+1
 #endif
 
 #define SLAP_SOCK_CLR_READ(fd) FD_CLR(fd, &slap_daemon.sd_readers)
 #define SLAP_SOCK_CLR_WRITE(fd)        FD_CLR(fd, &slap_daemon.sd_writers)
 
-#define        SLAP_ADD_SOCK(s) do {   \
+#define        SLAP_ADD_SOCK(s, l) do {        \
        SLAP_ADDTEST(s);        \
        FD_SET(s, &slap_daemon.sd_actives);     \
        FD_SET(s, &slap_daemon.sd_readers);     \
@@ -266,7 +293,7 @@ static struct slap_daemon {
 #define SLAP_EVENT_CLR_WRITE(fd)       FD_CLR(fd, &writefds)
 
 #define SLAP_EVENT_WAIT(tvp)   \
-       select( SLAP_MAXWAIT, &readfds, \
+       select( SLAP_EVENT_MAX, &readfds,       \
                nwriters > 0 ? &writefds : NULL, NULL, tvp )
 
 #define        SLAP_SOCK_SET_MUTE(s)   FD_CLR(s, &readfds)
@@ -388,9 +415,10 @@ void slapd_slp_dereg() {
  * If isactive, the descriptor is a live server session and is subject
  * to idletimeout control. Otherwise, the descriptor is a passive
  * listener or an outbound client session, and not subject to
- * idletimeout.
+ * idletimeout. The underlying event handler may record the Listener
+ * argument to differentiate Listener's from real sessions.
  */
-static void slapd_add(ber_socket_t s, int isactive) {
+static void slapd_add(ber_socket_t s, int isactive, Listener *sl) {
        ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
 
        assert( SLAP_SOCK_NOT_ACTIVE(s) );
@@ -399,7 +427,7 @@ static void slapd_add(ber_socket_t s, int isactive) {
                slap_daemon.sd_nactives++;
        }
 
-       SLAP_ADD_SOCK(s);
+       SLAP_ADD_SOCK(s, sl);
 
        Debug( LDAP_DEBUG_CONNS, "daemon: added %ldr\n",
                (long) s, 0, 0 );
@@ -419,8 +447,7 @@ void slapd_remove(ber_socket_t s, int wasactive, int wake) {
        waswriter = SLAP_SOCK_IS_WRITE(s);
 
        Debug( LDAP_DEBUG_CONNS, "daemon: removing %ld%s%s\n",
-               (long) s,
-           SLAP_SOCK_IS_READ(s) ? "r" : "",
+               (long) s, SLAP_SOCK_IS_READ(s) ? "r" : "",
                waswriter ? "w" : "" );
        if ( waswriter ) slap_daemon.sd_nwriters--;
 
@@ -951,8 +978,14 @@ static int slap_open_listener(
 #endif
 #ifdef LDAP_PF_LOCAL
                case AF_LOCAL:
-                       addrlen = sizeof(struct sockaddr_un);
-                       break;
+#ifdef LOCAL_CREDS
+               {
+                       int one = 1;
+                       setsockopt(l.sl_sd, 0, LOCAL_CREDS, &one, sizeof one);
+               }
+#endif
+               addrlen = sizeof(struct sockaddr_un);
+               break;
 #endif
                }
 
@@ -1444,7 +1477,7 @@ slapd_handle_listener(
                id, (long) s, peername, sl->sl_name.bv_val,
                0 );
 
-       slapd_add( s, 1 );
+       slapd_add( s, 1, NULL );
        return 0;
 }
 
@@ -1456,6 +1489,7 @@ slapd_daemon_task(
        int l;
        time_t  last_idle_check = 0;
        struct timeval idle;
+       int ebadf = 0;
 
 #define SLAPD_IDLE_CHECK_LIMIT 4
 
@@ -1473,7 +1507,7 @@ slapd_daemon_task(
                idle.tv_usec = 0;
        }
 
-       slapd_add( wake_sds[0], 0 );
+       slapd_add( wake_sds[0], 0, NULL );
 
        for ( l = 0; slap_listeners[l] != NULL; l++ ) {
                if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
@@ -1484,7 +1518,7 @@ slapd_daemon_task(
                 * are unnecessary.
                 */
                if ( slap_listeners[l]->sl_is_udp ) {
-                       slapd_add( slap_listeners[l]->sl_sd, 1 );
+                       slapd_add( slap_listeners[l]->sl_sd, 1, slap_listeners[l] );
                        continue;
                }
 #endif
@@ -1530,7 +1564,7 @@ slapd_daemon_task(
                        return( (void*)-1 );
                }
 
-               slapd_add( slap_listeners[l]->sl_sd, 0 );
+               slapd_add( slap_listeners[l]->sl_sd, 0, slap_listeners[l] );
        }
 
 #ifdef HAVE_NT_SERVICE_MANAGER
@@ -1546,7 +1580,6 @@ slapd_daemon_task(
                int at;
                ber_socket_t nfds, nrfds, nwfds;
 #define SLAPD_EBADF_LIMIT 16
-               int ebadf = 0;
 
                time_t  now;
 
@@ -1606,7 +1639,7 @@ slapd_daemon_task(
                            SLAP_SOCK_CLR_MUTE( slap_listeners[l]->sl_sd );
                }
 
-               nfds = SLAP_MAXWAIT;
+               nfds = SLAP_EVENT_MAX;
 
                if ( global_idletimeout && slap_daemon.sd_nactives )
                        at = 1;
@@ -1622,24 +1655,24 @@ slapd_daemon_task(
                else
                        tvp = NULL;
 
-               ldap_pvt_thread_mutex_lock( &syncrepl_rq.rq_mutex );
-               rtask = ldap_pvt_runqueue_next_sched( &syncrepl_rq, &cat );
+               ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
+               rtask = ldap_pvt_runqueue_next_sched( &slapd_rq, &cat );
                while ( cat && cat->tv_sec && cat->tv_sec <= now ) {
-                       if ( ldap_pvt_runqueue_isrunning( &syncrepl_rq, rtask )) {
-                               ldap_pvt_runqueue_resched( &syncrepl_rq, rtask, 0 );
+                       if ( ldap_pvt_runqueue_isrunning( &slapd_rq, rtask )) {
+                               ldap_pvt_runqueue_resched( &slapd_rq, rtask, 0 );
                        } else {
-                               ldap_pvt_runqueue_runtask( &syncrepl_rq, rtask );
-                               ldap_pvt_runqueue_resched( &syncrepl_rq, rtask, 0 );
-                               ldap_pvt_thread_mutex_unlock( &syncrepl_rq.rq_mutex );
+                               ldap_pvt_runqueue_runtask( &slapd_rq, rtask );
+                               ldap_pvt_runqueue_resched( &slapd_rq, rtask, 0 );
+                               ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
                                ldap_pvt_thread_pool_submit( &connection_pool,
                                                                                        rtask->routine, (void *) rtask );
-                               ldap_pvt_thread_mutex_lock( &syncrepl_rq.rq_mutex );
+                               ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
                        }
-                       rtask = ldap_pvt_runqueue_next_sched( &syncrepl_rq, &cat );
+                       rtask = ldap_pvt_runqueue_next_sched( &slapd_rq, &cat );
                }
-               ldap_pvt_thread_mutex_unlock( &syncrepl_rq.rq_mutex );
+               ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
 
-               if ( cat != NULL ) {
+               if ( cat && cat->tv_sec ) {
                        time_t diff = difftime( cat->tv_sec, now );
                        if ( diff == 0 )
                                diff = tdelta;
@@ -1687,10 +1720,12 @@ slapd_daemon_task(
 
                case 0:         /* timeout - let threads run */
                        ebadf = 0;
+#ifndef HAVE_YIELDING_SELECT
                        Debug( LDAP_DEBUG_CONNS, "daemon: select timeout - yielding\n",
                            0, 0, 0 );
 
                        ldap_pvt_thread_yield();
+#endif
                        continue;
 
                default:        /* something happened - deal with it */
@@ -1702,19 +1737,16 @@ slapd_daemon_task(
                        /* FALL THRU */
                }
 
-               /* We don't need to examine the event status for wake_sds;
-                * if waking is set and we woke up, we'll read whatever
-                * we can.
-                */
-               if ( waking ) {
+#if SLAP_EVENTS_ARE_INDEXED
+               if ( SLAP_EVENT_IS_READ( wake_sds[0] )) {
                        char c[BUFSIZ];
                        tcp_read( wake_sds[0], c, sizeof(c) );
                        waking = 0;
                        ns--;
+                       SLAP_EVENT_CLR_READ( wake_sds[0] );
                        continue;
                }
 
-#if SLAP_EVENTS_ARE_INDEXED
                /* The event slot equals the descriptor number - this is
                 * true for Unix select and poll. We treat Windows select
                 * like this too, even though it's a kludge.
@@ -1735,6 +1767,7 @@ slapd_daemon_task(
                        rc = slapd_handle_listener(slap_listeners[l]);
 
 #ifdef LDAP_CONNECTIONLESS
+                       /* This is a UDP session, let the data loop process it */
                        if ( rc ) continue;
 #endif
 
@@ -1745,7 +1778,9 @@ slapd_daemon_task(
 
                /* bypass the following tests if no descriptors left */
                if ( ns <= 0 ) {
+#ifndef HAVE_YIELDING_SELECT
                        ldap_pvt_thread_yield();
+#endif
                        continue;
                }
 
@@ -1819,6 +1854,7 @@ slapd_daemon_task(
                                }
                                slapd_close( wd );
                        }
+                       SLAP_EVENT_CLR_WRITE( wd );
                }
 
                for ( i = 0; nrfds > 0; i++ )
@@ -1855,14 +1891,94 @@ slapd_daemon_task(
         * all other connections last (as we do for select), we would need
         * to use multiple event handles and cascade them.
         *
-        * That seems like a bit of hassle. So the wake_sds check has moved
-        * above. For epoll and kqueue we can associate arbitrary data with
+        * That seems like a bit of hassle. So the wake_sds check has been
+        * skipped. For epoll and kqueue we can associate arbitrary data with
         * an event, so we could use pointers to the listener structure
         * instead of just the file descriptor. For /dev/poll we have to
         * search the listeners array for a matching descriptor.
         */
+               /* if waking is set and we woke up, we'll read whatever
+                * we can.
+                */
+               if ( waking ) {
+                       char c[BUFSIZ];
+                       tcp_read( wake_sds[0], c, sizeof(c) );
+                       waking = 0;
+                       ns--;
+                       continue;
+               }
+
+#ifdef LDAP_DEBUG
+               Debug( LDAP_DEBUG_CONNS, "daemon: activity on:", 0, 0, 0 );
+
+               for (i=0; i<ns; i++) {
+                       int     r, w;
+
+                       if ( SLAP_EVENT_IS_LISTENER(i)
+#ifdef LDAP_CONNECTIONLESS
+                       && !((SLAP_EVENT_LISTENER(i))->sl_is_udp)
 #endif
+                        ) continue;
+
+                       r = SLAP_EVENT_IS_READ( i );
+                       w = SLAP_EVENT_IS_WRITE( i );
+                       if ( r || w ) {
+                               Debug( LDAP_DEBUG_CONNS, " %d%s%s", SLAP_EVENT_FD(i),
+                                   r ? "r" : "", w ? "w" : "" );
+                       }
+               }
+#endif
+               for (i=0; i<ns; i++) {
+                       int rc = 1, fd;
+
+                       if ( SLAP_EVENT_IS_LISTENER(i) ) {
+                               rc = slapd_handle_listener( SLAP_EVENT_LISTENER( i ));
+                       }
+                       /* If we found a regular listener, rc is now zero, and we
+                        * can skip the data portion. But if it was a UDP listener
+                        * then rc is still 1, and we want to handle the data.
+                        */
+                       if ( rc ) {
+                               fd = SLAP_EVENT_FD( i );
+
+                               if( SLAP_EVENT_IS_WRITE( i ) ) {
+                                       Debug( LDAP_DEBUG_CONNS,
+                                               "daemon: write active on %d\n",
+                                               fd, 0, 0 );
+                                       /*
+                                        * NOTE: it is possible that the connection was closed
+                                        * and that the stream is now inactive.
+                                        * connection_write() must valid the stream is still
+                                        * active.
+                                        */
+
+                                       if ( connection_write( fd ) < 0 ) {
+                                               slapd_close( fd );
+                                               continue;
+                                       }
+                               }
+                               if( SLAP_EVENT_IS_READ( i ) ) {
+                                       Debug( LDAP_DEBUG_CONNS,
+                                               "daemon: read active on %d\n",
+                                               fd, 0, 0 );
+                                       /*
+                                        * NOTE: it is possible that the connection was closed
+                                        * and that the stream is now inactive.
+                                        * connection_read() must valid the stream is still
+                                        * active.
+                                        */
+
+                                       if ( connection_read( fd ) < 0 ) {
+                                               slapd_close( fd );
+                                       }
+                               }
+                       }
+               }
+#endif /* SLAP_EVENTS_ARE_INDEXED */
+
+#ifndef HAVE_YIELDING_SELECT
                ldap_pvt_thread_yield();
+#endif
        }
 
        if( slapd_shutdown == 1 ) {
@@ -2030,7 +2146,7 @@ slap_sig_wake( int sig )
 
 
 void slapd_add_internal(ber_socket_t s, int isactive) {
-       slapd_add(s, isactive);
+       slapd_add(s, isactive, NULL);
 }
 
 Listener ** slapd_get_listeners(void) {