]> git.evergreen-ils.org Git - OpenSRF.git/blob - src/libopensrf/osrf_prefork.c
a9f7c42cd403804b8ae73bf3eccca646d467f4ed
[OpenSRF.git] / src / libopensrf / osrf_prefork.c
1 /**
2         @file osrf_prefork.c
3         @brief Spawn and manage a collection of child process to service requests.
4
5         Spawn a collection of child processes, replacing them as needed.  Forward requests to them
6         and let the children do the work.
7
8         Each child processes some maximum number of requests before it terminates itself.  When a
9         child dies, either deliberately or otherwise, we can spawn another one to replace it,
10         keeping the number of children within a predefined range.
11
12         Use a doubly-linked circular list to keep track of the children to whom we have forwarded
13         a request, and who are still working on them.  Use a separate linear linked list to keep
14         track of children that are currently idle.  Move them back and forth as needed.
15
16         For each child, set up two pipes:
17         - One for the parent to send requests to the child.
18         - One for the child to notify the parent that it is available for another request.
19
20         The message sent to the child represents an XML stanza as received from Jabber.
21
22         When the child finishes processing the request, it writes the string "available" back
23         to the parent.  Then the parent knows that it can send that child another request.
24 */
25
26 #include <errno.h>
27 #include <signal.h>
28 #include <sys/types.h>
29 #include <sys/time.h>
30 #include <unistd.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <sys/select.h>
35 #include <sys/wait.h>
36
37 #include "opensrf/utils.h"
38 #include "opensrf/log.h"
39 #include "opensrf/transport_client.h"
40 #include "opensrf/osrf_stack.h"
41 #include "opensrf/osrf_settings.h"
42 #include "opensrf/osrf_application.h"
43
44 #define READ_BUFSIZE 1024
45 #define ABS_MAX_CHILDREN 256
46
47 typedef struct {
48         int max_requests;     /**< How many requests a child processes before terminating. */
49         int min_children;     /**< Minimum number of children to maintain. */
50         int max_children;     /**< Maximum number of children to maintain. */
51         int max_backlog_queue; /**< Maximum size of backlog queue. */
52         int fd;               /**< Unused. */
53         int data_to_child;    /**< Unused. */
54         int data_to_parent;   /**< Unused. */
55         int current_num_children;   /**< How many children are currently on the list. */
56         int keepalive;        /**< Keepalive time for stateful sessions. */
57         char* appname;        /**< Name of the application. */
58         /** Points to a circular linked list of children. */
59         struct prefork_child_struct* first_child;
60         /** List of of child processes that aren't doing anything at the moment and are
61                 therefore available to service a new request. */
62         struct prefork_child_struct* idle_list;
63         /** List of allocated but unused prefork_children, available for reuse.  Each one is just
64                 raw memory, apart from the "next" pointer used to stitch them together.  In particular,
65                 there is no child process for them, and the file descriptors are not open. */
66         struct prefork_child_struct* free_list;
67     struct prefork_child_struct* sighup_pending_list;
68         transport_client* connection;  /**< Connection to Jabber. */
69 } prefork_simple;
70
71 struct prefork_child_struct {
72         pid_t pid;            /**< Process ID of the child. */
73         int read_data_fd;     /**< Child uses to read request. */
74         int write_data_fd;    /**< Parent uses to write request. */
75         int read_status_fd;   /**< Parent reads to see if child is available. */
76         int write_status_fd;  /**< Child uses to notify parent when it's available again. */
77         int max_requests;     /**< How many requests a child can process before terminating. */
78         const char* appname;  /**< Name of the application. */
79         int keepalive;        /**< Keepalive time for stateful sessions. */
80         struct prefork_child_struct* next;  /**< Linkage pointer for linked list. */
81         struct prefork_child_struct* prev;  /**< Linkage pointer for linked list. */
82 };
83
84 typedef struct prefork_child_struct prefork_child;
85
86 /** Boolean.  Set to true by a signal handler when it traps SIGCHLD. */
87 static volatile sig_atomic_t child_dead;
88
89 static int prefork_simple_init( prefork_simple* prefork, transport_client* client,
90         int max_requests, int min_children, int max_children, int max_backlog_queue );
91 static prefork_child* launch_child( prefork_simple* forker );
92 static void prefork_launch_children( prefork_simple* forker );
93 static void prefork_run( prefork_simple* forker );
94 static void add_prefork_child( prefork_simple* forker, prefork_child* child );
95
96 static void del_prefork_child( prefork_simple* forker, pid_t pid );
97 static int check_children( prefork_simple* forker, int forever );
98 static int  prefork_child_process_request( prefork_child*, char* data );
99 static int prefork_child_init_hook( prefork_child* );
100 static prefork_child* prefork_child_init( prefork_simple* forker,
101         int read_data_fd, int write_data_fd,
102         int read_status_fd, int write_status_fd );
103
104 /* listens on the 'data_to_child' fd and wait for incoming data */
105 static void prefork_child_wait( prefork_child* child );
106 static void prefork_clear( prefork_simple*, bool graceful);
107 static void prefork_child_free( prefork_simple* forker, prefork_child* );
108 static void osrf_prefork_register_routers( const char* appname, bool unregister );
109 static void osrf_prefork_child_exit( prefork_child* );
110
111 static void sigchld_handler( int sig );
112 static void sigusr1_handler( int sig );
113 static void sigusr2_handler( int sig );
114 static void sigterm_handler( int sig );
115 static void sigint_handler( int sig );
116 static void sighup_handler( int sig );
117
118 /** Maintain a global pointer to the prefork_simple object
119  *  for the current process so we can refer to it later
120  *  for signal handling.  There will only ever be one
121  *  forker per process.
122  */
123 static prefork_simple *global_forker = NULL;
124
125 /**
126         @brief Spawn and manage a collection of drone processes for servicing requests.
127         @param appname Name of the application.
128         @return 0 if successful, or -1 if error.
129 */
130 int osrf_prefork_run( const char* appname ) {
131
132         if( !appname ) {
133                 osrfLogError( OSRF_LOG_MARK, "osrf_prefork_run requires an appname to run!");
134                 return -1;
135         }
136
137         set_proc_title( "OpenSRF Listener [%s]", appname );
138
139         int maxr = 1000;
140         int maxc = 10;
141         int maxbq = 1000;
142         int minc = 3;
143         int kalive = 5;
144
145         // Get configuration settings
146         osrfLogInfo( OSRF_LOG_MARK, "Loading config in osrf_forker for app %s", appname );
147
148         char* max_req      = osrf_settings_host_value( "/apps/%s/unix_config/max_requests", appname );
149         char* min_children = osrf_settings_host_value( "/apps/%s/unix_config/min_children", appname );
150         char* max_children = osrf_settings_host_value( "/apps/%s/unix_config/max_children", appname );
151         char* max_backlog_queue = osrf_settings_host_value( "/apps/%s/unix_config/max_backlog_queue", appname );
152         char* keepalive    = osrf_settings_host_value( "/apps/%s/keepalive", appname );
153
154         if( !keepalive )
155                 osrfLogWarning( OSRF_LOG_MARK, "Keepalive is not defined, assuming %d", kalive );
156         else
157                 kalive = atoi( keepalive );
158
159         if( !max_req )
160                 osrfLogWarning( OSRF_LOG_MARK, "Max requests not defined, assuming %d", maxr );
161         else
162                 maxr = atoi( max_req );
163
164         if( !min_children )
165                 osrfLogWarning( OSRF_LOG_MARK, "Min children not defined, assuming %d", minc );
166         else
167                 minc = atoi( min_children );
168
169         if( !max_children )
170                 osrfLogWarning( OSRF_LOG_MARK, "Max children not defined, assuming %d", maxc );
171         else
172                 maxc = atoi( max_children );
173
174         if( !max_backlog_queue )
175                 osrfLogWarning( OSRF_LOG_MARK, "Max backlog queue size not defined, assuming %d", maxbq );
176         else
177                 maxbq = atoi( max_backlog_queue );
178
179         free( keepalive );
180         free( max_req );
181         free( min_children );
182         free( max_children );
183         free( max_backlog_queue );
184         /* --------------------------------------------------- */
185
186         char* resc = va_list_to_string( "%s_listener", appname );
187
188         // Make sure that we haven't already booted
189         if( !osrfSystemBootstrapClientResc( NULL, NULL, resc )) {
190                 osrfLogError( OSRF_LOG_MARK, "Unable to bootstrap client for osrf_prefork_run()" );
191                 free( resc );
192                 return -1;
193         }
194
195         free( resc );
196
197         prefork_simple forker;
198
199         if( prefork_simple_init( &forker, osrfSystemGetTransportClient(), maxr, minc, maxc, maxbq )) {
200                 osrfLogError( OSRF_LOG_MARK,
201                         "osrf_prefork_run() failed to create prefork_simple object" );
202                 return -1;
203         }
204
205         // Finish initializing the prefork_simple.
206         forker.appname   = strdup( appname );
207         forker.keepalive = kalive;
208         global_forker = &forker;
209
210         // Spawn the children; put them in the idle list.
211         prefork_launch_children( &forker );
212
213         // Tell the router that you're open for business.
214         osrf_prefork_register_routers( appname, false );
215
216         signal( SIGUSR1, sigusr1_handler);
217         signal( SIGUSR2, sigusr2_handler);
218         signal( SIGTERM, sigterm_handler);
219         signal( SIGINT,  sigint_handler );
220         signal( SIGQUIT, sigint_handler );
221         signal( SIGHUP,  sighup_handler );
222
223         // Sit back and let the requests roll in
224         osrfLogInfo( OSRF_LOG_MARK, "Launching osrf_forker for app %s", appname );
225         prefork_run( &forker );
226
227         osrfLogWarning( OSRF_LOG_MARK, "prefork_run() returned - how??" );
228         prefork_clear( &forker, false );
229         return 0;
230 }
231
232 /**
233         @brief Register the application with a specified router.
234         @param appname Name of the application.
235         @param routerName Name of the router.
236         @param routerDomain Domain of the router.
237
238         Tell the router that you're open for business so that it can route requests to you.
239
240         Called only by the parent process.
241 */
242 static void osrf_prefork_send_router_registration(
243                 const char* appname, const char* routerName, 
244             const char* routerDomain, bool unregister ) {
245
246         // Get a pointer to the global transport_client
247         transport_client* client = osrfSystemGetTransportClient();
248
249         // Construct the Jabber address of the router
250         char* jid = va_list_to_string( "%s@%s/router", routerName, routerDomain );
251
252         // Create the registration message, and send it
253         transport_message* msg;
254     if (unregister) {
255
256             osrfLogInfo( OSRF_LOG_MARK, "%s un-registering with router %s", appname, jid );
257             msg = message_init( "unregistering", NULL, NULL, jid, NULL );
258             message_set_router_info( msg, NULL, NULL, appname, "unregister", 0 );
259
260     } else {
261
262             osrfLogInfo( OSRF_LOG_MARK, "%s registering with router %s", appname, jid );
263             msg = message_init( "registering", NULL, NULL, jid, NULL );
264             message_set_router_info( msg, NULL, NULL, appname, "register", 0 );
265     }
266
267         client_send_message( client, msg );
268
269         // Clean up
270         message_free( msg );
271         free( jid );
272 }
273
274 /**
275         @brief Register with a router, or not, according to some config settings.
276         @param appname Name of the application
277         @param RouterChunk A representation of part of the config file.
278
279         Parse a "complex" router configuration chunk.
280
281         Examine the services listed for a given router (normally in opensrf_core.xml).  If
282         there is an entry for this service, or if there are @em no services listed, then
283         register with this router.  Otherwise don't.
284
285         Called only by the parent process.
286 */
287 static void osrf_prefork_parse_router_chunk( 
288     const char* appname, const jsonObject* routerChunk, bool unregister ) {
289
290         const char* routerName = jsonObjectGetString( jsonObjectGetKeyConst( routerChunk, "name" ));
291         const char* domain = jsonObjectGetString( jsonObjectGetKeyConst( routerChunk, "domain" ));
292         const jsonObject* services = jsonObjectGetKeyConst( routerChunk, "services" );
293         osrfLogDebug( OSRF_LOG_MARK, "found router config with domain %s and name %s",
294                 routerName, domain );
295
296         if( services && services->type == JSON_HASH ) {
297                 osrfLogDebug( OSRF_LOG_MARK, "investigating router information..." );
298                 const jsonObject* service_obj = jsonObjectGetKeyConst( services, "service" );
299                 if( !service_obj )
300                         ;    // do nothing (shouldn't happen)
301                 else if( JSON_ARRAY == service_obj->type ) {
302                         // There are multiple services listed.  Register with this router
303                         // if and only if this service is on the list.
304                         int j;
305                         for( j = 0; j < service_obj->size; j++ ) {
306                                 const char* service = jsonObjectGetString( jsonObjectGetIndex( service_obj, j ));
307                                 if( service && !strcmp( appname, service ))
308                                         osrf_prefork_send_router_registration( appname, routerName, domain, unregister );
309                         }
310                 }
311                 else if( JSON_STRING == service_obj->type ) {
312                         // There's only one service listed.  Register with this router
313                         // if and only if this service is the one listed.
314                         if( !strcmp( appname, jsonObjectGetString( service_obj )) )
315                                 osrf_prefork_send_router_registration( appname, routerName, domain, unregister );
316                 }
317         } else {
318                 // This router is not restricted to any set of services,
319                 // so go ahead and register with it.
320                 osrf_prefork_send_router_registration( appname, routerName, domain, unregister );
321         }
322 }
323
324 /**
325         @brief Register the application with one or more routers, according to the configuration.
326         @param appname Name of the application.
327
328         Called only by the parent process.
329 */
330 static void osrf_prefork_register_routers( const char* appname, bool unregister ) {
331
332         jsonObject* routerInfo = osrfConfigGetValueObject( NULL, "/routers/router" );
333
334         int i;
335         for( i = 0; i < routerInfo->size; i++ ) {
336                 const jsonObject* routerChunk = jsonObjectGetIndex( routerInfo, i );
337
338                 if( routerChunk->type == JSON_STRING ) {
339                         /* this accomodates simple router configs */
340                         char* routerName = osrfConfigGetValue( NULL, "/router_name" );
341                         char* domain = osrfConfigGetValue( NULL, "/routers/router" );
342                         osrfLogDebug( OSRF_LOG_MARK, "found simple router settings with router name %s",
343                                 routerName );
344                         osrf_prefork_send_router_registration( appname, routerName, domain, unregister );
345
346                         free( routerName );
347                         free( domain );
348                 } else {
349                         osrf_prefork_parse_router_chunk( appname, routerChunk, unregister );
350                 }
351         }
352
353         jsonObjectFree( routerInfo );
354 }
355
356 /**
357         @brief Initialize a child process.
358         @param child Pointer to the prefork_child representing the new child process.
359         @return Zero if successful, or -1 if not.
360
361         Called only by child processes.  Actions:
362         - Connect to one or more cache servers
363         - Reconfigure logger, if necessary
364         - Discard parent's Jabber connection and open a new one
365         - Dynamically call an application-specific initialization routine
366         - Change the command line as reported by ps
367 */
368 static int prefork_child_init_hook( prefork_child* child ) {
369
370         if( !child ) return -1;
371         osrfLogDebug( OSRF_LOG_MARK, "Child init hook for child %d", child->pid );
372
373         // Connect to cache server(s).
374         osrfSystemInitCache();
375         char* resc = va_list_to_string( "%s_drone", child->appname );
376
377         // If we're a source-client, tell the logger now that we're a new process.
378         char* isclient = osrfConfigGetValue( NULL, "/client" );
379         if( isclient && !strcasecmp( isclient,"true" ))
380                 osrfLogSetIsClient( 1 );
381         free( isclient );
382
383         // Remove traces of our parent's socket connection so we can have our own.
384     // TODO: not necessary if parent disconnects first
385         osrfSystemIgnoreTransportClient();
386
387         // Connect to Jabber
388         if( !osrfSystemBootstrapClientResc( NULL, NULL, resc )) {
389                 osrfLogError( OSRF_LOG_MARK, "Unable to bootstrap client for osrf_prefork_run()" );
390                 free( resc );
391                 return -1;
392         }
393
394         free( resc );
395
396         // Dynamically call the application-specific initialization function
397         // from a previously loaded shared library.
398         if( ! osrfAppRunChildInit( child->appname )) {
399                 osrfLogDebug( OSRF_LOG_MARK, "Prefork child_init succeeded\n" );
400         } else {
401                 osrfLogError( OSRF_LOG_MARK, "Prefork child_init failed\n" );
402                 return -1;
403         }
404
405         // Change the command line as reported by ps
406         set_proc_title( "OpenSRF Drone [%s]", child->appname );
407         return 0;
408 }
409
410 /**
411         @brief Respond to a client request forwarded by the parent.
412         @param child Pointer to the state of the child process.
413         @param data Pointer to the raw XMPP message received from the parent.
414         @return 0 on success; non-zero means that the child process should clean itself up
415                 and terminate immediately, presumably due to a fatal error condition.
416
417         Called only by a child process.
418 */
419 static int prefork_child_process_request( prefork_child* child, char* data ) {
420         if( !child ) return 0;
421
422         transport_client* client = osrfSystemGetTransportClient();
423
424         // Make sure that we're still connected to Jabber; reconnect if necessary.
425         if( !client_connected( client )) {
426                 osrfSystemIgnoreTransportClient();
427                 osrfLogWarning( OSRF_LOG_MARK, "Reconnecting child to opensrf after disconnect..." );
428                 if( !osrf_system_bootstrap_client( NULL, NULL )) {
429                         osrfLogError( OSRF_LOG_MARK,
430                                 "Unable to bootstrap client in prefork_child_process_request()" );
431                         sleep( 1 );
432                         osrf_prefork_child_exit( child );
433                 }
434         }
435
436         // Construct the message from the xml.
437         transport_message* msg = new_message_from_xml( data );
438
439         // Respond to the transport message.  This is where method calls are buried.
440         osrfAppSession* session = osrf_stack_transport_handler( msg, child->appname );
441         if( !session )
442                 return 0;
443
444         int rc = session->panic;
445
446         if( rc ) {
447                 osrfLogWarning( OSRF_LOG_MARK,
448                         "Drone for session %s terminating immediately", session->session_id );
449                 osrfAppSessionFree( session );
450                 return rc;
451         }
452
453         if( session->stateless && session->state != OSRF_SESSION_CONNECTED ) {
454                 // We're no longer connected to the client, which presumably means that
455                 // we're done with this request.  Bail out.
456                 osrfAppSessionFree( session );
457                 return rc;
458         }
459
460         // If we get this far, then the client has opened an application connection so that it
461         // can send multiple requests directly to the same server drone, bypassing the router
462         // and the listener.  For example, it may need to do a database transaction, requiring
463         // multiple method calls within the same database session.
464
465         // Hence we go into a loop, responding to successive requests from the same client, until
466         // either the client disconnects or an error occurs.
467
468         osrfLogDebug( OSRF_LOG_MARK, "Entering keepalive loop for session %s", session->session_id );
469         int keepalive = child->keepalive;
470         int retval;
471         int recvd;
472         time_t start;
473         time_t end;
474
475         while( 1 ) {
476
477                 // Respond to any input messages.  This is where the method calls are buried.
478                 osrfLogDebug( OSRF_LOG_MARK,
479                         "osrf_prefork calling queue_wait [%d] in keepalive loop", keepalive );
480                 start   = time( NULL );
481                 retval  = osrf_app_session_queue_wait( session, keepalive, &recvd );
482                 end     = time( NULL );
483
484                 osrfLogDebug( OSRF_LOG_MARK, "Data received == %d", recvd );
485
486                 // Now we check a number of possible reasons to exit the loop.
487
488                 // If the method call decided to terminate immediately,
489                 // note that for future reference.
490                 if( session->panic )
491                         rc = 1;
492
493                 // If an error occurred when we tried to service the request, exit the loop.
494                 if( retval ) {
495                         osrfLogError( OSRF_LOG_MARK, "queue-wait returned non-success %d", retval );
496                         break;
497                 }
498
499                 // If the client disconnected, exit the loop.
500                 if( session->state != OSRF_SESSION_CONNECTED )
501                         break;
502
503                 // If we timed out while waiting for a request, exit the loop.
504                 if( !recvd && (end - start) >= keepalive ) {
505                         osrfLogInfo( OSRF_LOG_MARK,
506                                 "No request was received in %d seconds, exiting stateful session", keepalive );
507                         osrfAppSessionStatus(
508                                 session,
509                                 OSRF_STATUS_TIMEOUT,
510                                 "osrfConnectStatus",
511                                 0, "Disconnected on timeout" );
512
513                         break;
514                 }
515
516                 // If the child process has decided to terminate immediately, exit the loop.
517                 if( rc )
518                         break;
519         }
520
521         osrfLogDebug( OSRF_LOG_MARK, "Exiting keepalive loop for session %s", session->session_id );
522         osrfAppSessionFree( session );
523         return rc;
524 }
525
526 /**
527         @brief Partially initialize a prefork_simple provided by the caller.
528         @param prefork Pointer to a a raw prefork_simple to be initialized.
529         @param client Pointer to a transport_client (connection to Jabber).
530         @param max_requests The maximum number of requests that a child process may service
531                         before terminating.
532         @param min_children Minimum number of child processes to maintain.
533         @param max_children Maximum number of child processes to maintain.
534         @param max_backlog_queue Maximum size of backlog queue.
535         @return 0 if successful, or 1 if not (due to invalid parameters).
536 */
537 static int prefork_simple_init( prefork_simple* prefork, transport_client* client,
538                 int max_requests, int min_children, int max_children, int max_backlog_queue ) {
539
540         if( min_children > max_children ) {
541                 osrfLogError( OSRF_LOG_MARK,  "min_children (%d) is greater "
542                         "than max_children (%d)", min_children, max_children );
543                 return 1;
544         }
545
546         if( max_children > ABS_MAX_CHILDREN ) {
547                 osrfLogError( OSRF_LOG_MARK,  "max_children (%d) is greater than ABS_MAX_CHILDREN (%d)",
548                         max_children, ABS_MAX_CHILDREN );
549                 return 1;
550         }
551
552         osrfLogInfo( OSRF_LOG_MARK, "Prefork launching child with max_request=%d,"
553                 "min_children=%d, max_children=%d", max_requests, min_children, max_children );
554
555         /* flesh out the struct */
556         prefork->max_requests = max_requests;
557         prefork->min_children = min_children;
558         prefork->max_children = max_children;
559         prefork->max_backlog_queue = max_backlog_queue;
560         prefork->fd           = 0;
561         prefork->data_to_child = 0;
562         prefork->data_to_parent = 0;
563         prefork->current_num_children = 0;
564         prefork->keepalive    = 0;
565         prefork->appname      = NULL;
566         prefork->first_child  = NULL;
567         prefork->idle_list    = NULL;
568         prefork->free_list    = NULL;
569         prefork->connection   = client;
570         prefork->sighup_pending_list = NULL;
571
572         return 0;
573 }
574
575 /**
576         @brief Spawn a new child process and put it in the idle list.
577         @param forker Pointer to the prefork_simple that will own the process.
578         @return Pointer to the new prefork_child, or not at all.
579
580         Spawn a new child process.  Create a prefork_child for it and put it in the idle list.
581
582         After forking, the parent returns a pointer to the new prefork_child.  The child
583         services its quota of requests and then terminates without returning.
584 */
585 static prefork_child* launch_child( prefork_simple* forker ) {
586
587         pid_t pid;
588         int data_fd[2];
589         int status_fd[2];
590
591         // Set up the data and status pipes
592         if( pipe( data_fd ) < 0 ) { /* build the data pipe*/
593                 osrfLogError( OSRF_LOG_MARK,  "Pipe making error" );
594                 return NULL;
595         }
596
597         if( pipe( status_fd ) < 0 ) {/* build the status pipe */
598                 osrfLogError( OSRF_LOG_MARK,  "Pipe making error" );
599                 close( data_fd[1] );
600                 close( data_fd[0] );
601                 return NULL;
602         }
603
604         osrfLogInternal( OSRF_LOG_MARK, "Pipes: %d %d %d %d",
605                 data_fd[0], data_fd[1], status_fd[0], status_fd[1] );
606
607         // Create and initialize a prefork_child for the new process
608         prefork_child* child = prefork_child_init( forker, data_fd[0],
609                 data_fd[1], status_fd[0], status_fd[1] );
610
611         if( (pid=fork()) < 0 ) {
612                 osrfLogError( OSRF_LOG_MARK, "Forking Error" );
613                 prefork_child_free( forker, child );
614                 return NULL;
615         }
616
617         // Add the new child to the head of the idle list
618         child->next = forker->idle_list;
619         forker->idle_list = child;
620
621         if( pid > 0 ) {  /* parent */
622
623                 signal( SIGCHLD, sigchld_handler );
624                 ( forker->current_num_children )++;
625                 child->pid = pid;
626
627                 osrfLogDebug( OSRF_LOG_MARK, "Parent launched %d", pid );
628                 /* *no* child pipe FD's can be closed or the parent will re-use fd's that
629                         the children are currently using */
630                 return child;
631         }
632
633         else { /* child */
634
635                 // we don't want to adopt our parent's handlers.
636                 signal( SIGUSR1, SIG_DFL );
637                 signal( SIGUSR2, SIG_DFL );
638                 signal( SIGTERM, SIG_DFL );
639                 signal( SIGINT,  SIG_DFL );
640                 signal( SIGQUIT, SIG_DFL );
641                 signal( SIGCHLD, SIG_DFL );
642                 signal( SIGHUP,  SIG_DFL );
643
644                 osrfLogInternal( OSRF_LOG_MARK,
645                         "I am new child with read_data_fd = %d and write_status_fd = %d",
646                         child->read_data_fd, child->write_status_fd );
647
648                 child->pid = getpid();
649                 close( child->write_data_fd );
650                 close( child->read_status_fd );
651
652                 /* do the initing */
653                 if( prefork_child_init_hook( child ) == -1 ) {
654                         osrfLogError( OSRF_LOG_MARK,
655                                 "Forker child going away because we could not connect to OpenSRF..." );
656                         osrf_prefork_child_exit( child );
657                 }
658
659                 prefork_child_wait( child );      // Should exit without returning
660                 osrf_prefork_child_exit( child ); // Just to be sure
661                 return NULL;  // Unreachable, but it keeps the compiler happy
662         }
663 }
664
665 /**
666         @brief Terminate a child process.
667         @param child Pointer to the prefork_child representing the child process (not used).
668
669         Called only by child processes.  Dynamically call an application-specific shutdown
670         function from a previously loaded shared library; then exit.
671 */
672 static void osrf_prefork_child_exit( prefork_child* child ) {
673         osrfAppRunExitCode();
674         exit( 0 );
675 }
676
677 /**
678         @brief Launch all the child processes, putting them in the idle list.
679         @param forker Pointer to the prefork_simple that will own the children.
680
681         Called only by the parent process (in order to become a parent).
682 */
683 static void prefork_launch_children( prefork_simple* forker ) {
684         if( !forker ) return;
685         int c = 0;
686         while( c++ < forker->min_children )
687                 launch_child( forker );
688 }
689
690 /**
691         @brief Signal handler for SIGCHLD: note that a child process has terminated.
692         @param sig The value of the trapped signal; always SIGCHLD.
693
694         Set a boolean to be checked later.
695 */
696 static void sigchld_handler( int sig ) {
697         signal( SIGCHLD, sigchld_handler );
698         child_dead = 1;
699 }
700
701 /**
702         @brief Signal handler for SIGUSR1
703         @param sig The value of the trapped signal; always SIGUSR1.
704
705         Send unregister command to all registered routers.
706 */
707 static void sigusr1_handler( int sig ) {
708         if (!global_forker) return;
709         osrf_prefork_register_routers(global_forker->appname, true);
710         signal( SIGUSR1, sigusr1_handler );
711 }
712
713 /**
714         @brief Signal handler for SIGUSR2
715         @param sig The value of the trapped signal; always SIGUSR2.
716
717         Send register command to all known routers
718 */
719 static void sigusr2_handler( int sig ) {
720         if (!global_forker) return;
721         osrf_prefork_register_routers(global_forker->appname, false);
722         signal( SIGUSR2, sigusr2_handler );
723 }
724
725 /**
726         @brief Signal handler for SIGTERM
727         @param sig The value of the trapped signal; always SIGTERM
728
729         Perform a graceful prefork server shutdown.
730 */
731 static void sigterm_handler(int sig) {
732         if (!global_forker) return;
733         osrfLogInfo(OSRF_LOG_MARK, "server: received SIGTERM, shutting down");
734         prefork_clear(global_forker, true);
735         _exit(0);
736 }
737
738 /**
739         @brief Signal handler for SIGINT or SIGQUIT
740         @param sig The value of the trapped signal
741
742         Perform a non-graceful prefork server shutdown.
743 */
744 static void sigint_handler(int sig) {
745         if (!global_forker) return;
746         osrfLogInfo(OSRF_LOG_MARK, "server: received SIGINT/QUIT, shutting down");
747         prefork_clear(global_forker, false);
748         _exit(0);
749 }
750
751 static void sighup_handler(int sig) {
752     if (!global_forker) return;
753     osrfLogInfo(OSRF_LOG_MARK, "server: received SIGHUP, reloading config");
754
755     osrfConfig* oldConfig = osrfConfigGetDefaultConfig();
756     osrfConfig* newConfig = osrfConfigInit(
757         oldConfig->configFileName, oldConfig->configContext);
758
759     if (!newConfig) {
760         osrfLogError(OSRF_LOG_MARK, "Config reload failed");
761         return;
762     }
763
764     // frees oldConfig
765     osrfConfigSetDefaultConfig(newConfig); 
766     
767     // apply the log level from the reloaded file
768     char* log_level = osrfConfigGetValue(NULL, "/loglevel");
769     if(log_level) {
770         int level = atoi(log_level);
771         osrfLogSetLevel(level);
772     }
773
774     // Copy the list of active children into the sighup_pending list.
775     // Cloning is necessary, since the nodes in the active list, particularly
776     // their next/prev pointers, will start changing once we exit this func.
777     // sighup_pending_list is a non-circular, singly linked list.
778     prefork_child* cur_child = global_forker->first_child;
779     prefork_child* clone;
780
781     // the first_pid lets us know when we've made a full circle of the active 
782     // children
783     pid_t first_pid = 0;
784     while (cur_child && cur_child->pid != first_pid) {
785
786         if (!first_pid) first_pid = cur_child->pid;
787
788         // all we need to keep track of is the pid
789         clone = safe_malloc(sizeof(prefork_child));
790         clone->pid = cur_child->pid;
791         clone->next = NULL;
792
793         osrfLogDebug(OSRF_LOG_MARK, 
794             "Adding child %d to sighup pending list", clone->pid);
795
796         // add the clone to the front of the list
797         if (global_forker->sighup_pending_list) 
798             clone->next = global_forker->sighup_pending_list;
799         global_forker->sighup_pending_list = clone;
800
801         cur_child = cur_child->next;
802     }
803
804     // Kill all idle children.
805     // Let them get cleaned up through the normal response-handling cycle
806     cur_child = global_forker->idle_list;
807     while (cur_child) {
808         osrfLogDebug(OSRF_LOG_MARK, "Killing child in SIGHUP %d", cur_child->pid);
809         kill(cur_child->pid, SIGKILL);
810         cur_child = cur_child->next;
811     }
812 }
813     
814
815 /**
816         @brief Replenish the collection of child processes, after one has terminated.
817         @param forker Pointer to the prefork_simple that manages the child processes.
818
819         The parent calls this function when it notices (via a signal handler) that
820         a child process has died.
821
822         Wait on the dead children so that they won't be zombies.  Spawn new ones as needed
823         to maintain at least a minimum number.
824 */
825 static void reap_children( prefork_simple* forker ) {
826
827         pid_t child_pid;
828
829         // Reset our boolean so that we can detect any further terminations.
830         child_dead = 0;
831
832         // Bury the children so that they won't be zombies.  WNOHANG means that waitpid() returns
833         // immediately if there are no waitable children, instead of waiting for more to die.
834         // Ignore the return code of the child.  We don't do an autopsy.
835         while( (child_pid = waitpid( -1, NULL, WNOHANG )) > 0 ) {
836                 --forker->current_num_children;
837                 del_prefork_child( forker, child_pid );
838         }
839
840         // Spawn more children as needed.
841         while( forker->current_num_children < forker->min_children )
842                 launch_child( forker );
843 }
844
845 /**
846         @brief Read transport_messages and dispatch them to child processes for servicing.
847         @param forker Pointer to the prefork_simple that manages the child processes.
848
849         This is the main loop of the parent process, and once entered, does not exit.
850
851         For each usable transport_message received: look for an idle child to service it.  If
852         no idle children are available, either spawn a new one or, if we've already spawned the
853         maximum number of children, wait for one to become available.  Once a child is available
854         by whatever means, write an XML version of the input message, to a pipe designated for
855         use by that child.
856 */
857 static void prefork_run( prefork_simple* forker ) {
858
859         if( NULL == forker->idle_list )
860                 return;   // No available children, and we haven't even started yet
861
862         transport_message* cur_msg = NULL;
863
864         // The backlog queue accumulates messages received while there
865         // are not yet children available to process them. While the
866         // transport client maintains its own queue of messages, sweeping
867         // the transport client's queue in the backlog queue gives us the
868         // ability to set a limit on the size of the backlog queue (and
869         // then to drop messages once the backlog queue has filled up)
870         transport_message* backlog_queue_head = NULL;
871         transport_message* backlog_queue_tail = NULL;
872         int backlog_queue_size = 0;
873
874         while( 1 ) {
875
876                 if( forker->first_child == NULL && forker->idle_list == NULL ) {/* no more children */
877                         osrfLogWarning( OSRF_LOG_MARK, "No more children..." );
878                         return;
879                 }
880
881                 int received_from_network = 0;
882                 if ( backlog_queue_size == 0 ) {
883                         // Wait indefinitely for an input message
884                         osrfLogDebug( OSRF_LOG_MARK, "Forker going into wait for data..." );
885                         cur_msg = client_recv( forker->connection, -1 );
886                         received_from_network = 1;
887                 } else {
888                         // See if any messages are immediately available
889                         cur_msg = client_recv( forker->connection, 0 );
890                         if ( cur_msg != NULL )
891                                 received_from_network = 1;
892                 }
893
894                 if (received_from_network) {
895                         if( cur_msg == NULL ) {
896                                 // most likely a signal was received.  clean up any recently
897                                 // deceased children and try again.
898                                 if(child_dead)
899                                         reap_children(forker);
900                                 continue;
901                         }
902
903                         if (cur_msg->error_type) {
904                                 osrfLogInfo(OSRF_LOG_MARK,
905                                         "Listener received an XMPP error message.  "
906                                         "Likely a bounced message. sender=%s", cur_msg->sender);
907                                 if(child_dead)
908                                         reap_children(forker);
909                                 continue;
910                         }
911
912                         message_prepare_xml( cur_msg );
913                         const char* msg_data = cur_msg->msg_xml;
914                         if( ! msg_data || ! *msg_data ) {
915                                 osrfLogWarning( OSRF_LOG_MARK, "Received % message from %s, thread %",
916                                         (msg_data ? "empty" : "NULL"), cur_msg->sender, cur_msg->thread );
917                                 message_free( cur_msg );
918                                 continue;       // Message not usable; go on to the next one.
919                         }
920
921                         // stick message onto queue
922                         cur_msg->next = NULL;
923                         if (backlog_queue_size == 0) {
924                                 backlog_queue_head = cur_msg;
925                                 backlog_queue_tail = cur_msg;
926                         } else {
927                                 if (backlog_queue_size >= forker->max_backlog_queue) {
928                                         osrfLogWarning ( OSRF_LOG_MARK, "Reached backlog queue limit of %d; dropping "
929                                                 "latest message",
930                                                 forker->max_backlog_queue );
931                                         osrfMessage* err = osrf_message_init( STATUS, 1, 1 );
932                                         osrf_message_set_status_info( err, "osrfMethodException",
933                                                 "Service unavailable: no available children and backlog queue at limit",
934                                                 OSRF_STATUS_SERVICEUNAVAILABLE );
935                                         char *data = osrf_message_serialize( err );
936                                         osrfMessageFree( err );
937                                         transport_message* tresponse = message_init( data, "", cur_msg->thread, cur_msg->router_from, cur_msg->recipient );
938                                         message_set_osrf_xid(tresponse, cur_msg->osrf_xid);
939                                         free( data );
940                                         transport_client* client = osrfSystemGetTransportClient();
941                                         client_send_message( client, tresponse );
942                                         message_free( tresponse );
943                                         message_free(cur_msg);
944                                         continue;
945                                 }
946                                 backlog_queue_tail->next = cur_msg;
947                                 backlog_queue_tail = cur_msg;
948                                 osrfLogWarning( OSRF_LOG_MARK, "Adding message to non-empty backlog queue." );
949                         }
950                         backlog_queue_size++;
951                 }
952
953                 if (backlog_queue_size == 0) {
954                         // strictly speaking, this check may be redundant, but
955                         // from this point forward we can be sure that the
956                         // backlog queue has at least one message in it and
957                         // that if we can find a child to process it, we want to
958                         // process the head of that queue.
959                         continue;
960                 }
961
962                 cur_msg = backlog_queue_head;
963
964                 int honored = 0;     /* will be set to true when we service the request */
965                 int no_recheck = 0;
966
967                 while( ! honored ) {
968
969                         if( !no_recheck ) {
970                                 if(check_children( forker, 0 ) < 0) {
971                     continue; // check failed, try again
972                                 }
973             }
974             no_recheck = 0;
975
976                         osrfLogDebug( OSRF_LOG_MARK, "Server received inbound data" );
977
978                         prefork_child* cur_child = NULL;
979
980                         // Look for an available child in the idle list.  Since the idle list operates
981                         // as a stack, the child we get is the one that was most recently active, or
982                         // most recently spawned.  That means it's the one most likely still to be in
983                         // physical memory, and the one least likely to have to be swapped in.
984                         while( forker->idle_list ) {
985
986                                 osrfLogDebug( OSRF_LOG_MARK, "Looking for idle child" );
987                                 // Grab the prefork_child at the head of the idle list
988                                 cur_child = forker->idle_list;
989                                 forker->idle_list = cur_child->next;
990                                 cur_child->next = NULL;
991
992                                 osrfLogInternal( OSRF_LOG_MARK,
993                                         "Searching for available child. cur_child->pid = %d", cur_child->pid );
994                                 osrfLogInternal( OSRF_LOG_MARK, "Current num children %d",
995                                         forker->current_num_children );
996
997                                 osrfLogDebug( OSRF_LOG_MARK, "forker sending data to %d", cur_child->pid );
998                                 osrfLogInternal( OSRF_LOG_MARK, "Writing to child fd %d",
999                                         cur_child->write_data_fd );
1000
1001                                 const char* msg_data = cur_msg->msg_xml;
1002                                 int written = write( cur_child->write_data_fd, msg_data, strlen( msg_data ) + 1 );
1003                                 if( written < 0 ) {
1004                                         // This child appears to be dead or unusable.  Discard it.
1005                                         osrfLogWarning( OSRF_LOG_MARK, "Write returned error %d: %s",
1006                                                 errno, strerror( errno ));
1007                                         kill( cur_child->pid, SIGKILL );
1008                                         del_prefork_child( forker, cur_child->pid );
1009                                         continue;
1010                                 }
1011
1012                                 add_prefork_child( forker, cur_child );  // Add it to active list
1013                                 honored = 1;
1014                                 break;
1015                         }
1016
1017                         /* if none available, add a new child if we can */
1018                         if( ! honored ) {
1019                                 osrfLogDebug( OSRF_LOG_MARK, "Not enough children, attempting to add..." );
1020
1021                                 if( forker->current_num_children < forker->max_children ) {
1022                                         osrfLogDebug( OSRF_LOG_MARK,  "Launching new child with current_num = %d",
1023                                                 forker->current_num_children );
1024
1025                                         launch_child( forker );  // Put a new child into the idle list
1026                                         if( forker->idle_list ) {
1027
1028                                                 // Take the new child from the idle list
1029                                                 prefork_child* new_child = forker->idle_list;
1030                                                 forker->idle_list = new_child->next;
1031                                                 new_child->next = NULL;
1032
1033                                                 osrfLogDebug( OSRF_LOG_MARK, "Writing to new child fd %d : pid %d",
1034                                                         new_child->write_data_fd, new_child->pid );
1035
1036                                                 const char* msg_data = cur_msg->msg_xml;
1037                                                 int written = write(
1038                                                         new_child->write_data_fd, msg_data, strlen( msg_data ) + 1 );
1039                                                 if( written < 0 ) {
1040                                                         // This child appears to be dead or unusable.  Discard it.
1041                                                         osrfLogWarning( OSRF_LOG_MARK, "Write returned error %d: %s",
1042                                                                 errno, strerror( errno ));
1043                                                         kill( cur_child->pid, SIGKILL );
1044                                                         del_prefork_child( forker, cur_child->pid );
1045                                                 } else {
1046                                                         add_prefork_child( forker, new_child );
1047                                                         honored = 1;
1048                                                 }
1049                                         }
1050                 } else {
1051                     osrfLogWarning( OSRF_LOG_MARK, "Could not launch a new child as %d children "
1052                         "were already running; consider increasing max_children for this "
1053                         "application higher than %d in the OpenSRF configuration if this "
1054                         "message occurs frequently",
1055                         forker->current_num_children, forker->max_children );
1056                 }
1057             }
1058
1059                         if( child_dead )
1060                                 reap_children( forker );
1061
1062                         if( !honored ) {
1063                                 break;
1064                         }
1065
1066                 } // end while( ! honored )
1067
1068                 if ( honored ) {
1069                         backlog_queue_head = cur_msg->next;
1070                         backlog_queue_size--;
1071                         cur_msg->next = NULL;
1072                         message_free( cur_msg );
1073                 }
1074
1075         } /* end top level listen loop */
1076 }
1077
1078
1079 /**
1080         @brief See if any children have become available.
1081         @param forker Pointer to the prefork_simple that owns the children.
1082         @param forever Boolean: true if we should wait indefinitely.
1083     @return 0 or greater if successful, -1 on select error/interrupt
1084
1085         Call select() for all the children in the active list.  Read each active file
1086         descriptor and move the corresponding child to the idle list.
1087
1088         If @a forever is true, wait indefinitely for input.  Otherwise return immediately if
1089         there are no active file descriptors.
1090 */
1091 static int check_children( prefork_simple* forker, int forever ) {
1092
1093         if( child_dead )
1094                 reap_children( forker );
1095
1096         if( NULL == forker->first_child ) {
1097                 // If forever is true, then we're here because we've run out of idle
1098                 // processes, so there should be some active ones around, except during
1099                 // graceful shutdown, as we wait for all active children to become idle.
1100                 // If forever is false, then the children may all be idle, and that's okay.
1101                 if( forever )
1102                         osrfLogDebug( OSRF_LOG_MARK, "No active child processes to check" );
1103                 return 0;
1104         }
1105
1106         int select_ret;
1107         fd_set read_set;
1108         FD_ZERO( &read_set );
1109         int max_fd = 0;
1110         int n;
1111
1112         // Prepare to select() on pipes from all the active children
1113         prefork_child* cur_child = forker->first_child;
1114         do {
1115                 if( cur_child->read_status_fd > max_fd )
1116                         max_fd = cur_child->read_status_fd;
1117                 FD_SET( cur_child->read_status_fd, &read_set );
1118                 cur_child = cur_child->next;
1119         } while( cur_child != forker->first_child );
1120
1121         FD_CLR( 0, &read_set ); /* just to be sure */
1122
1123         if( forever ) {
1124
1125                 if( (select_ret=select( max_fd + 1, &read_set, NULL, NULL, NULL )) == -1 ) {
1126                         osrfLogWarning( OSRF_LOG_MARK, "Select returned error %d on check_children: %s",
1127                                 errno, strerror( errno ));
1128                 }
1129                 osrfLogInfo( OSRF_LOG_MARK,
1130                         "select() completed after waiting on children to become available" );
1131
1132         } else {
1133
1134                 struct timeval tv;
1135                 tv.tv_sec   = 0;
1136                 tv.tv_usec  = 0;
1137
1138                 if( (select_ret=select( max_fd + 1, &read_set, NULL, NULL, &tv )) == -1 ) {
1139                         osrfLogWarning( OSRF_LOG_MARK, "Select returned error %d on check_children: %s",
1140                                 errno, strerror( errno ));
1141                 }
1142         }
1143
1144     if( select_ret <= 0 ) // we're done here
1145                 return select_ret;
1146
1147         // Check each child in the active list.
1148         // If it has responded, move it to the idle list.
1149         cur_child = forker->first_child;
1150         prefork_child* next_child = NULL;
1151         int num_handled = 0;
1152         do {
1153                 next_child = cur_child->next;
1154                 if( FD_ISSET( cur_child->read_status_fd, &read_set )) {
1155                         osrfLogDebug( OSRF_LOG_MARK,
1156                                 "Server received status from a child %d", cur_child->pid );
1157
1158                         num_handled++;
1159
1160                         /* now suck off the data */
1161                         char buf[64];
1162                         if( (n=read( cur_child->read_status_fd, buf, sizeof( buf ) - 1 )) < 0 ) {
1163                                 osrfLogWarning( OSRF_LOG_MARK,
1164                                         "Read error after select in child status read with errno %d: %s",
1165                                         errno, strerror( errno ));
1166                         }
1167                         else {
1168                                 buf[n] = '\0';
1169                                 osrfLogDebug( OSRF_LOG_MARK,  "Read %d bytes from status buffer: %s", n, buf );
1170                         }
1171
1172
1173             // if this child is in the sighup_pending list, kill the child,
1174             // but leave it in the active list so that it won't be picked
1175             // for new work.  When reap_children() next runs, it will be 
1176             // properly cleaned up.
1177             prefork_child* hup_child = forker->sighup_pending_list;
1178             prefork_child* prev_hup_child = NULL;
1179             int hup_cleanup = 0;
1180
1181             while (hup_child) {
1182                 pid_t hup_pid = hup_child->pid;
1183                 if (hup_pid == cur_child->pid) {
1184
1185                     osrfLogDebug(OSRF_LOG_MARK, 
1186                         "server: killing previously-active child after "
1187                         "receiving SIGHUP: %d", hup_pid);
1188
1189                     if (forker->sighup_pending_list == hup_child) {
1190                         // hup_child is the first (maybe only) in the list
1191                         forker->sighup_pending_list = hup_child->next;
1192                     } else {
1193                         // splice it from the list
1194                         prev_hup_child->next = hup_child->next;
1195                     }
1196
1197                     free(hup_child); // clean up the thin clone
1198                     kill(hup_pid, SIGKILL);
1199                     hup_cleanup = 1;
1200                     break;
1201                 }
1202
1203                 prev_hup_child = hup_child;
1204                 hup_child = hup_child->next;
1205             }
1206
1207             if (!hup_cleanup) {
1208
1209                 // Remove the child from the active list
1210                 if( forker->first_child == cur_child ) {
1211                     if( cur_child->next == cur_child ) {
1212                         // only child in the active list
1213                         forker->first_child = NULL;   
1214                     } else {
1215                         forker->first_child = cur_child->next;
1216                     }
1217                 }
1218                 cur_child->next->prev = cur_child->prev;
1219                 cur_child->prev->next = cur_child->next;
1220
1221                 // Add it to the idle list
1222                 cur_child->prev = NULL;
1223                 cur_child->next = forker->idle_list;
1224                 forker->idle_list = cur_child;
1225             }
1226         }
1227
1228         cur_child = next_child;
1229     } while( forker->first_child && forker->first_child != next_child );
1230
1231     return select_ret;
1232 }
1233
1234 /**
1235         @brief Service up a set maximum number of requests; then shut down.
1236         @param child Pointer to the prefork_child representing the child process.
1237
1238         Called only by child process.
1239
1240         Enter a loop, for up to max_requests iterations.  On each iteration:
1241         - Wait indefinitely for a request from the parent.
1242         - Service the request.
1243         - Increment a counter.  If the limit hasn't been reached, notify the parent that you
1244         are available for another request.
1245
1246         After exiting the loop, shut down and terminate the process.
1247 */
1248 static void prefork_child_wait( prefork_child* child ) {
1249
1250         int i,n;
1251         growing_buffer* gbuf = buffer_init( READ_BUFSIZE );
1252         char buf[READ_BUFSIZE];
1253
1254         for( i = 0; i < child->max_requests; i++ ) {
1255
1256                 n = -1;
1257                 int gotdata = 0;    // boolean; set to true if we get data
1258                 clr_fl( child->read_data_fd, O_NONBLOCK );
1259
1260                 // Read a request from the parent, via a pipe, into a growing_buffer.
1261                 while( (n = read( child->read_data_fd, buf, READ_BUFSIZE-1 )) > 0 ) {
1262                         buf[n] = '\0';
1263                         osrfLogDebug( OSRF_LOG_MARK, "Prefork child read %d bytes of data", n );
1264                         if( !gotdata ) {
1265                                 set_fl( child->read_data_fd, O_NONBLOCK );
1266                                 gotdata = 1;
1267                         }
1268                         buffer_add_n( gbuf, buf, n );
1269                 }
1270
1271                 if( errno == EAGAIN )
1272                         n = 0;
1273
1274                 if( errno == EPIPE ) {
1275                         osrfLogDebug( OSRF_LOG_MARK, "C child attempted read on broken pipe, exiting..." );
1276                         break;
1277                 }
1278
1279                 int terminate_now = 0;     // Boolean
1280
1281                 if( n < 0 ) {
1282                         osrfLogWarning( OSRF_LOG_MARK,
1283                                 "Prefork child read returned error with errno %d", errno );
1284                         break;
1285
1286                 } else if( gotdata ) {
1287                         // Process the request
1288                         osrfLogDebug( OSRF_LOG_MARK, "Prefork child got a request.. processing.." );
1289                         terminate_now = prefork_child_process_request( child, gbuf->buf );
1290                         buffer_reset( gbuf );
1291                 }
1292
1293                 if( terminate_now ) {
1294                         // We're terminating prematurely -- presumably due to a fatal error condition.
1295                         osrfLogWarning( OSRF_LOG_MARK, "Prefork child terminating abruptly" );
1296                         break;
1297                 }
1298
1299                 if( i < child->max_requests - 1 ) {
1300                         // Report back to the parent for another request.
1301                         size_t msg_len = 9;
1302                         ssize_t len = write(
1303                                 child->write_status_fd, "available" /*less than 64 bytes*/, msg_len );
1304                         if( len != msg_len ) {
1305                                 osrfLogError( OSRF_LOG_MARK,
1306                                         "Drone terminating: unable to notify listener of availability: %s",
1307                                         strerror( errno ));
1308                                 buffer_free( gbuf );
1309                                 osrf_prefork_child_exit( child );
1310                         }
1311                 }
1312         }
1313
1314         buffer_free( gbuf );
1315
1316         osrfLogDebug( OSRF_LOG_MARK, "Child with max-requests=%d, num-served=%d exiting...[%ld]",
1317                 child->max_requests, i, (long) getpid());
1318
1319         osrf_prefork_child_exit( child );
1320 }
1321
1322 /**
1323         @brief Add a prefork_child to the end of the active list.
1324         @param forker Pointer to the prefork_simple that owns the list.
1325         @param child Pointer to the prefork_child to be added.
1326 */
1327 static void add_prefork_child( prefork_simple* forker, prefork_child* child ) {
1328
1329         if( forker->first_child == NULL ) {
1330                 // Simplest case: list is initially empty.
1331                 forker->first_child = child;
1332                 child->next = child;
1333                 child->prev = child;
1334         } else {
1335                 // Find the last node in the circular list.
1336                 prefork_child* last_child = forker->first_child->prev;
1337
1338                 // Insert the new child between the last and first children.
1339                 last_child->next = child;
1340                 child->prev      = last_child;
1341                 child->next      = forker->first_child;
1342                 forker->first_child->prev = child;
1343         }
1344 }
1345
1346 /**
1347         @brief Delete and destroy a dead child from our list.
1348         @param forker Pointer to the prefork_simple that owns the dead child.
1349         @param pid Process ID of the dead child.
1350
1351         Look for the dead child first in the list of active children.  If you don't find it
1352         there, look in the list of idle children.  If you find it, remove it from whichever
1353         list it's on, and destroy it.
1354 */
1355 static void del_prefork_child( prefork_simple* forker, pid_t pid ) {
1356
1357         osrfLogDebug( OSRF_LOG_MARK, "Deleting Child: %d", pid );
1358
1359         prefork_child* cur_child = NULL;
1360
1361         // Look first in the active list
1362         if( forker->first_child ) {
1363                 cur_child = forker->first_child; /* current pointer */
1364                 while( cur_child->pid != pid && cur_child->next != forker->first_child )
1365                         cur_child = cur_child->next;
1366
1367                 if( cur_child->pid == pid ) {
1368                         // We found the right node.  Remove it from the list.
1369                         if( cur_child->next == cur_child )
1370                                 forker->first_child = NULL;    // only child in the list
1371                         else {
1372                                 if( forker->first_child == cur_child )
1373                                         forker->first_child = cur_child->next;  // Reseat forker->first_child
1374
1375                                 // Stitch the adjacent nodes together
1376                                 cur_child->prev->next = cur_child->next;
1377                                 cur_child->next->prev = cur_child->prev;
1378                         }
1379                 } else
1380                         cur_child = NULL;  // Didn't find it in the active list
1381         }
1382
1383         if( ! cur_child ) {
1384                 // Maybe it's in the idle list.  This can happen if, for example,
1385                 // a child is killed by a signal while it's between requests.
1386
1387                 prefork_child* prev = NULL;
1388                 cur_child = forker->idle_list;
1389                 while( cur_child && cur_child->pid != pid ) {
1390                         prev = cur_child;
1391                         cur_child = cur_child->next;
1392                 }
1393
1394                 if( cur_child ) {
1395                         // Detach from the list
1396                         if( prev )
1397                                 prev->next = cur_child->next;
1398                         else
1399                                 forker->idle_list = cur_child->next;
1400                 } // else we can't find it
1401         }
1402
1403         // If we found the node, destroy it.
1404         if( cur_child )
1405                 prefork_child_free( forker, cur_child );
1406 }
1407
1408 /**
1409         @brief Create and initialize a prefork_child.
1410         @param forker Pointer to the prefork_simple that will own the prefork_child.
1411         @param read_data_fd Used by child to read request from parent.
1412         @param write_data_fd Used by parent to write request to child.
1413         @param read_status_fd Used by parent to read status from child.
1414         @param write_status_fd Used by child to write status to parent.
1415         @return Pointer to the newly created prefork_child.
1416
1417         The calling code is responsible for freeing the prefork_child by calling
1418         prefork_child_free().
1419 */
1420 static prefork_child* prefork_child_init( prefork_simple* forker,
1421         int read_data_fd, int write_data_fd,
1422         int read_status_fd, int write_status_fd ) {
1423
1424         // Allocate a prefork_child -- from the free list if possible, or from
1425         // the heap if necessary.  The free list is a non-circular, singly-linked list.
1426         prefork_child* child;
1427         if( forker->free_list ) {
1428                 child = forker->free_list;
1429                 forker->free_list = child->next;
1430         } else
1431                 child = safe_malloc( sizeof( prefork_child ));
1432
1433         child->pid              = 0;
1434         child->read_data_fd     = read_data_fd;
1435         child->write_data_fd    = write_data_fd;
1436         child->read_status_fd   = read_status_fd;
1437         child->write_status_fd  = write_status_fd;
1438         child->max_requests     = forker->max_requests;
1439         child->appname          = forker->appname;  // We don't make a separate copy
1440         child->keepalive        = forker->keepalive;
1441         child->next             = NULL;
1442         child->prev             = NULL;
1443
1444         return child;
1445 }
1446
1447 /**
1448         @brief Terminate all child processes and clear out a prefork_simple.
1449         @param prefork Pointer to the prefork_simple to be cleared out.
1450
1451         We do not deallocate the prefork_simple itself, just its contents.
1452 */
1453 static void prefork_clear( prefork_simple* prefork, bool graceful ) {
1454
1455         // always de-register routers before killing child processes (or waiting
1456         // for them to complete) so that new requests are directed elsewhere.
1457         osrf_prefork_register_routers(global_forker->appname, true);
1458
1459         while( prefork->first_child ) {
1460
1461                 if (graceful) {
1462                         // wait for at least one active child to become idle, then repeat.
1463                         // once complete, all children will be idle and cleaned up below.
1464                         osrfLogInfo(OSRF_LOG_MARK, "graceful shutdown waiting...");
1465                         check_children(prefork, 1);
1466
1467                 } else {
1468                         // Kill and delete all the active children
1469                         kill( prefork->first_child->pid, SIGKILL );
1470                         del_prefork_child( prefork, prefork->first_child->pid );
1471                 }
1472         }
1473
1474         if (graceful) {
1475                 osrfLogInfo(OSRF_LOG_MARK,
1476                         "all active children are now idle in graceful shutdown");
1477         }
1478
1479         // Kill all the idle prefork children, close their file
1480         // descriptors, and move them to the free list.
1481         prefork_child* child = prefork->idle_list;
1482         prefork->idle_list = NULL;
1483         while( child ) {
1484                 prefork_child* temp = child->next;
1485                 kill( child->pid, SIGKILL );
1486                 prefork_child_free( prefork, child );
1487                 child = temp;
1488         }
1489         //prefork->current_num_children = 0;
1490
1491         // Physically free the free list of prefork_children.
1492         child = prefork->free_list;
1493         prefork->free_list = NULL;
1494         while( child ) {
1495                 prefork_child* temp = child->next;
1496                 free( child );
1497                 child = temp;
1498         }
1499
1500         // Close the Jabber connection
1501         client_free( prefork->connection );
1502         prefork->connection = NULL;
1503
1504         // After giving the child processes a second to terminate, wait on them so that they
1505         // don't become zombies.  We don't wait indefinitely, so it's possible that some
1506         // children will survive a bit longer.
1507         sleep( 1 );
1508         while( (waitpid( -1, NULL, WNOHANG )) > 0 ) {
1509                 --prefork->current_num_children;
1510         }
1511
1512         free( prefork->appname );
1513         prefork->appname = NULL;
1514 }
1515
1516 /**
1517         @brief Destroy and deallocate a prefork_child.
1518         @param forker Pointer to the prefork_simple that owns the prefork_child.
1519         @param child Pointer to the prefork_child to be destroyed.
1520 */
1521 static void prefork_child_free( prefork_simple* forker, prefork_child* child ) {
1522         close( child->read_data_fd );
1523         close( child->write_data_fd );
1524         close( child->read_status_fd );
1525         close( child->write_status_fd );
1526
1527         // Stick the prefork_child in a free list for potential reuse.  This is a
1528         // non-circular, singly linked list.
1529         child->prev = NULL;
1530         child->next = forker->free_list;
1531         forker->free_list = child;
1532 }