4 #include <sys/socket.h>
7 #include <netinet/in.h>
12 #include <sys/select.h>
16 #include "ldapconfig.h"
18 #include <sys/filio.h>
19 #else /* NEED_FILIO */
20 #include <sys/ioctl.h>
21 #endif /* NEED_FILIO */
24 #endif /* USE_SYSCONF */
26 extern Operation *op_add();
28 #ifndef SYSERRLIST_IN_STDIO
30 extern char *sys_errlist[];
32 extern time_t currenttime;
33 extern pthread_mutex_t currenttime_mutex;
34 extern int active_threads;
35 extern pthread_mutex_t active_threads_mutex;
36 extern pthread_mutex_t new_conn_mutex;
37 extern int slapd_shutdown;
38 extern pthread_t listener_tid;
40 extern pthread_mutex_t ops_mutex;
47 static void set_shutdown();
48 static void do_nothing();
57 unsigned long len, tag, msgid;
60 struct sockaddr_in addr;
67 dtblsize = sysconf( _SC_OPEN_MAX );
68 #else /* USE_SYSCONF */
69 dtblsize = getdtablesize();
70 #endif /* USE_SYSCONF */
72 * Add greg@greg.rim.or.jp
74 if(dtblsize > FD_SETSIZE) {
75 dtblsize = FD_SETSIZE;
77 c = (Connection *) ch_calloc( 1, dtblsize * sizeof(Connection) );
79 for ( i = 0; i < dtblsize; i++ ) {
85 c[i].c_sb.sb_options = LBER_NO_READ_AHEAD;
86 c[i].c_sb.sb_naddr = 0;
87 c[i].c_sb.sb_ber.ber_buf = NULL;
88 c[i].c_sb.sb_ber.ber_ptr = NULL;
89 c[i].c_sb.sb_ber.ber_end = NULL;
90 c[i].c_writewaiter = 0;
92 pthread_mutex_init( &c[i].c_dnmutex,
93 pthread_mutexattr_default );
94 pthread_mutex_init( &c[i].c_opsmutex,
95 pthread_mutexattr_default );
96 pthread_mutex_init( &c[i].c_pdumutex,
97 pthread_mutexattr_default );
98 pthread_cond_init( &c[i].c_wcv, pthread_condattr_default );
101 if ( (tcps = socket( AF_INET, SOCK_STREAM, 0 )) == -1 ) {
102 Debug( LDAP_DEBUG_ANY, "socket() failed errno %d (%s)", errno,
103 errno > -1 && errno < sys_nerr ? sys_errlist[errno] :
109 if ( setsockopt( tcps, SOL_SOCKET, SO_REUSEADDR, (char *) &i,
110 sizeof(i) ) == -1 ) {
111 Debug( LDAP_DEBUG_ANY, "setsockopt() failed errno %d (%s)",
112 errno, errno > -1 && errno < sys_nerr ? sys_errlist[errno] :
116 (void) memset( (void *) &addr, '\0', sizeof(addr) );
117 addr.sin_family = AF_INET;
118 addr.sin_addr.s_addr = INADDR_ANY;
119 addr.sin_port = htons( port );
120 if ( bind( tcps, (struct sockaddr *) &addr, sizeof(addr) ) == -1 ) {
121 Debug( LDAP_DEBUG_ANY, "bind() failed errno %d (%s)\n",
122 errno, errno > -1 && errno < sys_nerr ? sys_errlist[errno] :
127 if ( listen( tcps, 5 ) == -1 ) {
128 Debug( LDAP_DEBUG_ANY, "listen() failed errno %d (%s)",
129 errno, errno > -1 && errno < sys_nerr ? sys_errlist[errno] :
134 (void) SIGNAL( SIGPIPE, SIG_IGN );
135 (void) SIGNAL( SIGUSR1, (void *) do_nothing );
136 (void) SIGNAL( SIGUSR2, (void *) set_shutdown );
137 (void) SIGNAL( SIGTERM, (void *) set_shutdown );
138 (void) SIGNAL( SIGINT, (void *) set_shutdown );
139 (void) SIGNAL( SIGHUP, (void *) set_shutdown );
141 Debug( LDAP_DEBUG_ANY, "slapd starting\n", 0, 0, 0 );
143 if ( (fp = fopen( SLAPD_PIDFILE, "w" )) != NULL ) {
144 fprintf( fp, "%d\n", getpid() );
148 #ifdef SLAPD_ARGSFILE
149 if ( (fp = fopen( SLAPD_ARGSFILE, "w" )) != NULL ) {
150 for ( i = 0; i < g_argc; i++ ) {
151 fprintf( fp, "%s ", g_argv[i] );
158 while ( !slapd_shutdown ) {
159 struct sockaddr_in from;
165 FD_ZERO( &writefds );
167 FD_SET( tcps, &readfds );
169 pthread_mutex_lock( &active_threads_mutex );
170 Debug( LDAP_DEBUG_CONNS,
171 "listening for connections on %d, activity on:",
173 for ( i = 0; i < dtblsize; i++ ) {
174 if ( c[i].c_sb.sb_sd != -1 ) {
175 FD_SET( c[i].c_sb.sb_sd, &readfds );
177 if ( c[i].c_writewaiter ) {
178 FD_SET( c[i].c_sb.sb_sd, &writefds );
180 Debug( LDAP_DEBUG_CONNS, " %dr%s", i,
181 c[i].c_writewaiter ? "w" : "", 0 );
184 Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
188 Debug( LDAP_DEBUG_CONNS, "before select active_threads %d\n",
189 active_threads, 0, 0 );
190 #ifdef PTHREAD_PREEMPTIVE
193 tvp = active_threads ? &zero : NULL;
195 pthread_mutex_unlock( &active_threads_mutex );
197 switch ( select( dtblsize, &readfds, &writefds, 0, tvp ) ) {
198 case -1: /* failure - try again */
199 Debug( LDAP_DEBUG_CONNS,
200 "select failed errno %d (%s)\n",
201 errno, errno > -1 && errno < sys_nerr ?
202 sys_errlist[errno] : "unknown", 0 );
205 case 0: /* timeout - let threads run */
206 Debug( LDAP_DEBUG_CONNS, "select timeout - yielding\n",
211 default: /* something happened - deal with it */
212 Debug( LDAP_DEBUG_CONNS, "select activity\n", 0, 0, 0 );
215 pthread_mutex_lock( ¤ttime_mutex );
216 time( ¤ttime );
217 pthread_mutex_unlock( ¤ttime_mutex );
220 pthread_mutex_lock( &new_conn_mutex );
221 if ( FD_ISSET( tcps, &readfds ) ) {
223 if ( (ns = accept( tcps, (struct sockaddr *) &from,
225 Debug( LDAP_DEBUG_ANY,
226 "accept() failed errno %d (%s)", errno,
227 errno > -1 && errno < sys_nerr ?
228 sys_errlist[errno] : "unknown", 0 );
229 pthread_mutex_unlock( &new_conn_mutex );
232 if ( ioctl( ns, FIONBIO, (caddr_t) &on ) == -1 ) {
233 Debug( LDAP_DEBUG_ANY,
234 "FIONBIO ioctl on %d faled\n", ns, 0, 0 );
236 c[ns].c_sb.sb_sd = ns;
237 Debug( LDAP_DEBUG_CONNS, "new connection on %d\n", ns,
240 pthread_mutex_lock( &ops_mutex );
241 c[ns].c_connid = num_conns++;
242 pthread_mutex_unlock( &ops_mutex );
244 if ( getpeername( ns, (struct sockaddr *) &from, &len )
247 #ifdef REVERSE_LOOKUP
248 hp = gethostbyaddr( (char *)
249 &(from.sin_addr.s_addr),
250 sizeof(from.sin_addr.s_addr), AF_INET );
255 Statslog( LDAP_DEBUG_STATS,
256 "conn=%d fd=%d connection from %s (%s)\n",
257 c[ns].c_connid, ns, hp == NULL ? "unknown"
258 : hp->h_name, inet_ntoa( from.sin_addr ),
261 if ( c[ns].c_addr != NULL ) {
262 free( c[ns].c_addr );
264 c[ns].c_addr = strdup( inet_ntoa(
266 if ( c[ns].c_domain != NULL ) {
267 free( c[ns].c_domain );
269 c[ns].c_domain = strdup( hp == NULL ? "" :
271 /* normalize the domain */
272 for ( s = c[ns].c_domain; *s; s++ ) {
276 Statslog( LDAP_DEBUG_STATS,
277 "conn=%d fd=%d connection from unknown\n",
278 c[ns].c_connid, ns, 0, 0, 0 );
280 pthread_mutex_lock( &c[ns].c_dnmutex );
281 if ( c[ns].c_dn != NULL ) {
285 pthread_mutex_unlock( &c[ns].c_dnmutex );
286 c[ns].c_starttime = currenttime;
287 c[ns].c_opsinitiated = 0;
288 c[ns].c_opscompleted = 0;
290 pthread_mutex_unlock( &new_conn_mutex );
292 Debug( LDAP_DEBUG_CONNS, "activity on:", 0, 0, 0 );
293 for ( i = 0; i < dtblsize; i++ ) {
296 r = FD_ISSET( i, &readfds );
297 w = FD_ISSET( i, &writefds );
298 if ( i != tcps && (r || w) ) {
299 Debug( LDAP_DEBUG_CONNS, " %d%s%s", i,
300 r ? "r" : "", w ? "w" : "" );
303 Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
305 for ( i = 0; i < dtblsize; i++ ) {
306 if ( i == tcps || (! FD_ISSET( i, &readfds ) &&
307 ! FD_ISSET( i, &writefds )) ) {
311 if ( FD_ISSET( i, &writefds ) ) {
312 Debug( LDAP_DEBUG_CONNS,
313 "signaling write waiter on %d\n", i, 0, 0 );
315 pthread_mutex_lock( &active_threads_mutex );
316 pthread_cond_signal( &c[i].c_wcv );
317 c[i].c_writewaiter = 0;
319 pthread_mutex_unlock( &active_threads_mutex );
322 if ( FD_ISSET( i, &readfds ) ) {
323 Debug( LDAP_DEBUG_CONNS,
324 "read activity on %d\n", i, 0, 0 );
326 connection_activity( &c[i] );
334 pthread_mutex_lock( &active_threads_mutex );
335 Debug( LDAP_DEBUG_ANY,
336 "slapd shutting down - waiting for %d threads to terminate\n",
337 active_threads, 0, 0 );
338 while ( active_threads > 0 ) {
339 pthread_mutex_unlock( &active_threads_mutex );
341 pthread_mutex_lock( &active_threads_mutex );
343 pthread_mutex_unlock( &active_threads_mutex );
345 /* let backends do whatever cleanup they need to do */
346 Debug( LDAP_DEBUG_TRACE,
347 "slapd shutting down - waiting for backends to close down\n", 0, 0,
350 Debug( LDAP_DEBUG_ANY, "slapd stopping\n", 0, 0, 0 );
356 Debug( LDAP_DEBUG_ANY, "slapd got shutdown signal\n", 0, 0, 0 );
358 pthread_kill( listener_tid, SIGUSR1 );
359 (void) SIGNAL( SIGUSR2, (void *) set_shutdown );
360 (void) SIGNAL( SIGTERM, (void *) set_shutdown );
361 (void) SIGNAL( SIGINT, (void *) set_shutdown );
362 (void) SIGNAL( SIGHUP, (void *) set_shutdown );
368 Debug( LDAP_DEBUG_TRACE, "slapd got SIGUSR1\n", 0, 0, 0 );
369 (void) SIGNAL( SIGUSR1, (void *) do_nothing );