]> git.sur5r.net Git - openldap/blob - servers/slapd/daemon.c
fix SIGUNUSED typo
[openldap] / servers / slapd / daemon.c
1
2 /* Revision history
3  *
4  * 5-Jun-96     hodges
5  *      Added locking of new_conn_mutex when traversing the c[] array.
6  */
7
8 #include <stdio.h>
9 #include <string.h>
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <errno.h>
13 #include <sys/time.h>
14 #include <netinet/in.h>
15 #include <arpa/inet.h>
16 #include <netdb.h>
17 #include <signal.h>
18 #ifdef _AIX
19 #include <sys/select.h>
20 #endif
21 #include "slap.h"
22 #include "portable.h"
23 #include "ldapconfig.h"
24 #ifdef NEED_FILIO
25 #include <sys/filio.h>
26 #else /* NEED_FILIO */
27 #include <sys/ioctl.h>
28 #endif /* NEED_FILIO */
29 #ifdef USE_SYSCONF
30 #include <unistd.h>
31 #endif /* USE_SYSCONF */
32
33 extern Operation        *op_add();
34
35 #ifndef SYSERRLIST_IN_STDIO
36 extern int              sys_nerr;
37 extern char             *sys_errlist[];
38 #endif
39 extern time_t           currenttime;
40 extern pthread_mutex_t  currenttime_mutex;
41 extern int              active_threads;
42 extern pthread_mutex_t  active_threads_mutex;
43 extern pthread_mutex_t  new_conn_mutex;
44 extern int              slapd_shutdown;
45 extern pthread_t        listener_tid;
46 extern int              num_conns;
47 extern pthread_mutex_t  ops_mutex;
48 extern int              g_argc;
49 extern char             **g_argv;
50
51 int             dtblsize;
52 Connection      *c;
53
54 static void     set_shutdown();
55 static void     do_nothing();
56
57 void
58 slapd_daemon(
59     int port
60 )
61 {
62         Operation               *o;
63         BerElement              ber;
64         unsigned long           len, tag, msgid;
65         int                     i;
66         int                     tcps, ns;
67         struct sockaddr_in      addr;
68         fd_set                  readfds;
69         fd_set                  writefds;
70         FILE                    *fp;
71         int                     on = 1;
72
73 #ifdef USE_SYSCONF
74         dtblsize = sysconf( _SC_OPEN_MAX );
75 #else /* USE_SYSCONF */
76         dtblsize = getdtablesize();
77 #endif /* USE_SYSCONF */
78         /*
79          * Add greg@greg.rim.or.jp
80          */
81         if(dtblsize > FD_SETSIZE) {
82                 dtblsize = FD_SETSIZE;
83         }
84         c = (Connection *) ch_calloc( 1, dtblsize * sizeof(Connection) );
85
86         for ( i = 0; i < dtblsize; i++ ) {
87                 c[i].c_dn = NULL;
88                 c[i].c_addr = NULL;
89                 c[i].c_domain = NULL;
90                 c[i].c_ops = NULL;
91                 c[i].c_sb.sb_sd = -1;
92                 c[i].c_sb.sb_options = LBER_NO_READ_AHEAD;
93                 c[i].c_sb.sb_naddr = 0;
94                 c[i].c_sb.sb_ber.ber_buf = NULL;
95                 c[i].c_sb.sb_ber.ber_ptr = NULL;
96                 c[i].c_sb.sb_ber.ber_end = NULL;
97                 c[i].c_writewaiter = 0;
98                 c[i].c_connid = 0;
99                 pthread_mutex_init( &c[i].c_dnmutex,
100                     pthread_mutexattr_default );
101                 pthread_mutex_init( &c[i].c_opsmutex,
102                     pthread_mutexattr_default );
103                 pthread_mutex_init( &c[i].c_pdumutex,
104                     pthread_mutexattr_default );
105                 pthread_cond_init( &c[i].c_wcv, pthread_condattr_default );
106         }
107
108         if ( (tcps = socket( AF_INET, SOCK_STREAM, 0 )) == -1 ) {
109                 Debug( LDAP_DEBUG_ANY, "socket() failed errno %d (%s)", errno,
110                     errno > -1 && errno < sys_nerr ? sys_errlist[errno] :
111                     "unknown", 0 );
112                 exit( 1 );
113         }
114
115         i = 1;
116         if ( setsockopt( tcps, SOL_SOCKET, SO_REUSEADDR, (char *) &i,
117             sizeof(i) ) == -1 ) {
118                 Debug( LDAP_DEBUG_ANY, "setsockopt() failed errno %d (%s)",
119                     errno, errno > -1 && errno < sys_nerr ? sys_errlist[errno] :
120                     "unknown", 0 );
121         }
122
123         (void) memset( (void *) &addr, '\0', sizeof(addr) );
124         addr.sin_family = AF_INET;
125         addr.sin_addr.s_addr = INADDR_ANY;
126         addr.sin_port = htons( port );
127         if ( bind( tcps, (struct sockaddr *) &addr, sizeof(addr) ) == -1 ) {
128                 Debug( LDAP_DEBUG_ANY, "bind() failed errno %d (%s)\n",
129                     errno, errno > -1 && errno < sys_nerr ? sys_errlist[errno] :
130                     "unknown", 0 );
131                 exit( 1 );
132         }
133
134         if ( listen( tcps, 5 ) == -1 ) {
135                 Debug( LDAP_DEBUG_ANY, "listen() failed errno %d (%s)",
136                     errno, errno > -1 && errno < sys_nerr ? sys_errlist[errno] :
137                     "unknown", 0 );
138                 exit( 1 );
139         }
140
141         (void) SIGNAL( SIGPIPE, SIG_IGN );
142 #ifdef SIGSTKFLT
143         (void) SIGNAL( SIGSTKFLT, (void *) do_nothing );
144 #else
145         (void) SIGNAL( SIGUSR1, (void *) do_nothing );
146 #endif
147 #ifdef SIGUNUSED
148         (void) SIGNAL( SIGUNUSED, (void *) set_shutdown );
149 #else
150         (void) SIGNAL( SIGUSR2, (void *) set_shutdown );
151 #endif
152         (void) SIGNAL( SIGTERM, (void *) set_shutdown );
153         (void) SIGNAL( SIGINT, (void *) set_shutdown );
154         (void) SIGNAL( SIGHUP, (void *) set_shutdown );
155
156         Debug( LDAP_DEBUG_ANY, "slapd starting\n", 0, 0, 0 );
157 #ifdef SLAPD_PIDFILE
158         if ( (fp = fopen( SLAPD_PIDFILE, "w" )) != NULL ) {
159                 fprintf( fp, "%d\n", getpid() );
160                 fclose( fp );
161         }
162 #endif
163 #ifdef SLAPD_ARGSFILE
164         if ( (fp = fopen( SLAPD_ARGSFILE, "w" )) != NULL ) {
165                 for ( i = 0; i < g_argc; i++ ) {
166                         fprintf( fp, "%s ", g_argv[i] );
167                 }
168                 fprintf( fp, "\n" );
169                 fclose( fp );
170         }
171 #endif
172
173         while ( !slapd_shutdown ) {
174                 struct sockaddr_in      from;
175                 struct hostent          *hp;
176                 struct timeval          zero;
177                 struct timeval          *tvp;
178                 int                     len, pid;
179
180                 FD_ZERO( &writefds );
181                 FD_ZERO( &readfds );
182                 FD_SET( tcps, &readfds );
183
184                 pthread_mutex_lock( &active_threads_mutex );
185                 Debug( LDAP_DEBUG_CONNS,
186                     "listening for connections on %d, activity on:",
187                     tcps, 0, 0 );
188
189                 pthread_mutex_lock( &new_conn_mutex );
190                 for ( i = 0; i < dtblsize; i++ ) {
191                         if ( c[i].c_sb.sb_sd != -1 ) {
192                                 FD_SET( c[i].c_sb.sb_sd, &readfds );
193
194                                 if ( c[i].c_writewaiter ) {
195                                         FD_SET( c[i].c_sb.sb_sd, &writefds );
196                                 }
197                                 Debug( LDAP_DEBUG_CONNS, " %dr%s", i,
198                                     c[i].c_writewaiter ? "w" : "", 0 );
199                         }
200                 }
201                 Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
202                 pthread_mutex_unlock( &new_conn_mutex );
203
204                 zero.tv_sec = 0;
205                 zero.tv_usec = 0;
206                 Debug( LDAP_DEBUG_CONNS, "before select active_threads %d\n",
207                     active_threads, 0, 0 );
208 #ifdef PTHREAD_PREEMPTIVE
209                 tvp = NULL;
210 #else
211                 tvp = active_threads ? &zero : NULL;
212 #endif
213                 pthread_mutex_unlock( &active_threads_mutex );
214
215                 switch ( select( dtblsize, &readfds, &writefds, 0, tvp ) ) {
216                 case -1:        /* failure - try again */
217                         Debug( LDAP_DEBUG_CONNS,
218                             "select failed errno %d (%s)\n",
219                             errno, errno > -1 && errno < sys_nerr ?
220                             sys_errlist[errno] : "unknown", 0 );
221                         continue;
222
223                 case 0:         /* timeout - let threads run */
224                         Debug( LDAP_DEBUG_CONNS, "select timeout - yielding\n",
225                             0, 0, 0 );
226                         pthread_yield();
227                         continue;
228
229                 default:        /* something happened - deal with it */
230                         Debug( LDAP_DEBUG_CONNS, "select activity\n", 0, 0, 0 );
231                         ;       /* FALL */
232                 }
233                 pthread_mutex_lock( &currenttime_mutex );
234                 time( &currenttime );
235                 pthread_mutex_unlock( &currenttime_mutex );
236
237                 /* new connection */
238                 pthread_mutex_lock( &new_conn_mutex );
239                 if ( FD_ISSET( tcps, &readfds ) ) {
240                         len = sizeof(from);
241                         if ( (ns = accept( tcps, (struct sockaddr *) &from,
242                             &len )) == -1 ) {
243                                 Debug( LDAP_DEBUG_ANY,
244                                     "accept() failed errno %d (%s)", errno,
245                                     errno > -1 && errno < sys_nerr ?
246                                     sys_errlist[errno] : "unknown", 0 );
247                                 pthread_mutex_unlock( &new_conn_mutex );
248                                 continue;
249                         }
250                         if ( ioctl( ns, FIONBIO, (caddr_t) &on ) == -1 ) {
251                                 Debug( LDAP_DEBUG_ANY,
252                                     "FIONBIO ioctl on %d faled\n", ns, 0, 0 );
253                         }
254                         c[ns].c_sb.sb_sd = ns;
255                         Debug( LDAP_DEBUG_CONNS, "new connection on %d\n", ns,
256                             0, 0 );
257
258                         pthread_mutex_lock( &ops_mutex );
259                         c[ns].c_connid = num_conns++;
260                         pthread_mutex_unlock( &ops_mutex );
261                         len = sizeof(from);
262                         if ( getpeername( ns, (struct sockaddr *) &from, &len )
263                             == 0 ) {
264                                 char    *s;
265 #ifdef REVERSE_LOOKUP
266                                 hp = gethostbyaddr( (char *)
267                                     &(from.sin_addr.s_addr),
268                                     sizeof(from.sin_addr.s_addr), AF_INET );
269 #else
270                                 hp = NULL;
271 #endif
272
273                                 Statslog( LDAP_DEBUG_STATS,
274                                     "conn=%d fd=%d connection from %s (%s)\n",
275                                     c[ns].c_connid, ns, hp == NULL ? "unknown"
276                                     : hp->h_name, inet_ntoa( from.sin_addr ),
277                                     0 );
278
279                                 if ( c[ns].c_addr != NULL ) {
280                                         free( c[ns].c_addr );
281                                 }
282                                 c[ns].c_addr = strdup( inet_ntoa(
283                                     from.sin_addr ) );
284                                 if ( c[ns].c_domain != NULL ) {
285                                         free( c[ns].c_domain );
286                                 }
287                                 c[ns].c_domain = strdup( hp == NULL ? "" :
288                                     hp->h_name );
289                                 /* normalize the domain */
290                                 for ( s = c[ns].c_domain; *s; s++ ) {
291                                         *s = TOLOWER( *s );
292                                 }
293                         } else {
294                                 Statslog( LDAP_DEBUG_STATS,
295                                     "conn=%d fd=%d connection from unknown\n",
296                                     c[ns].c_connid, ns, 0, 0, 0 );
297                         }
298                         pthread_mutex_lock( &c[ns].c_dnmutex );
299                         if ( c[ns].c_dn != NULL ) {
300                                 free( c[ns].c_dn );
301                                 c[ns].c_dn = NULL;
302                         }
303                         pthread_mutex_unlock( &c[ns].c_dnmutex );
304                         c[ns].c_starttime = currenttime;
305                         c[ns].c_opsinitiated = 0;
306                         c[ns].c_opscompleted = 0;
307                 }
308                 pthread_mutex_unlock( &new_conn_mutex );
309
310                 Debug( LDAP_DEBUG_CONNS, "activity on:", 0, 0, 0 );
311                 for ( i = 0; i < dtblsize; i++ ) {
312                         int     r, w;
313
314                         r = FD_ISSET( i, &readfds );
315                         w = FD_ISSET( i, &writefds );
316                         if ( i != tcps && (r || w) ) {
317                                 Debug( LDAP_DEBUG_CONNS, " %d%s%s", i,
318                                     r ? "r" : "", w ? "w" : "" );
319                         }
320                 }
321                 Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
322
323                 for ( i = 0; i < dtblsize; i++ ) {
324                         if ( i == tcps || (! FD_ISSET( i, &readfds ) &&
325                             ! FD_ISSET( i, &writefds )) ) {
326                                 continue;
327                         }
328
329                         if ( FD_ISSET( i, &writefds ) ) {
330                                 Debug( LDAP_DEBUG_CONNS,
331                                     "signaling write waiter on %d\n", i, 0, 0 );
332
333                                 pthread_mutex_lock( &active_threads_mutex );
334                                 pthread_cond_signal( &c[i].c_wcv );
335                                 c[i].c_writewaiter = 0;
336                                 active_threads++;
337                                 pthread_mutex_unlock( &active_threads_mutex );
338                         }
339
340                         if ( FD_ISSET( i, &readfds ) ) {
341                                 Debug( LDAP_DEBUG_CONNS,
342                                     "read activity on %d\n", i, 0, 0 );
343
344                                 connection_activity( &c[i] );
345                         }
346                 }
347
348                 pthread_yield();
349         }
350
351         close( tcps );
352         pthread_mutex_lock( &active_threads_mutex );
353         Debug( LDAP_DEBUG_ANY,
354             "slapd shutting down - waiting for %d threads to terminate\n",
355             active_threads, 0, 0 );
356         while ( active_threads > 0 ) {
357                 pthread_mutex_unlock( &active_threads_mutex );
358                 pthread_yield();
359                 pthread_mutex_lock( &active_threads_mutex );
360         }
361         pthread_mutex_unlock( &active_threads_mutex );
362
363         /* let backends do whatever cleanup they need to do */
364         Debug( LDAP_DEBUG_TRACE,
365             "slapd shutting down - waiting for backends to close down\n", 0, 0,
366             0 );
367         be_close();
368         Debug( LDAP_DEBUG_ANY, "slapd stopping\n", 0, 0, 0 );
369 }
370
371 static void
372 set_shutdown()
373 {
374         Debug( LDAP_DEBUG_ANY, "slapd got shutdown signal\n", 0, 0, 0 );
375         slapd_shutdown = 1;
376 #ifdef SIGSTKFLT
377         pthread_kill( listener_tid, SIGSTKFLT );
378 #else
379         pthread_kill( listener_tid, SIGUSR1 );
380 #endif
381 #ifdef SIGUNUSED
382         (void) SIGNAL( SIGUNUSED, (void *) set_shutdown );
383 #else
384         (void) SIGNAL( SIGUSR2, (void *) set_shutdown );
385 #endif
386         (void) SIGNAL( SIGTERM, (void *) set_shutdown );
387         (void) SIGNAL( SIGINT, (void *) set_shutdown );
388         (void) SIGNAL( SIGHUP, (void *) set_shutdown );
389 }
390
391 static void
392 do_nothing()
393 {
394         Debug( LDAP_DEBUG_TRACE, "slapd got do_nothing signal\n", 0, 0, 0 );
395 #ifdef SIGSTKFLT
396         (void) SIGNAL( SIGSTKFLT, (void *) do_nothing );
397 #else
398         (void) SIGNAL( SIGUSR1, (void *) do_nothing );
399 #endif
400 }