X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fdaemon.c;h=2893a905f90c1f05de7eb85f2332dd0cd2605439;hb=b94a77687075b0eb2d54d087b8b956d197c1023c;hp=5cc423dc98f74a68e88ed7c6c72a08686603fb8f;hpb=b7d4e1a5f125358b49307256672a0db7f425a4e5;p=openldap diff --git a/servers/slapd/daemon.c b/servers/slapd/daemon.c index 5cc423dc98..2893a905f9 100644 --- a/servers/slapd/daemon.c +++ b/servers/slapd/daemon.c @@ -1,7 +1,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * 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 @@ -40,6 +40,12 @@ #include "ldap_rq.h" +#undef HAVE_EPOLL + +#if defined(HAVE_SYS_EPOLL_H) && defined(HAVE_EPOLL) +#include +#endif + #ifdef HAVE_TCPD #include #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= 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; isl_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