6 static char *rcsid_gdb_fserv_c = "$Header$";
10 /************************************************************************
14 * GDB - Routines to implement forking servers.
16 * Author: Noah Mendelsohn
17 * Copyright: 1986 MIT Project Athena
18 * For copying and distribution information, please see
19 * the file <mit-copyright.h>.
21 ************************************************************************/
23 #include <mit-copyright.h>
25 #include <sys/types.h>
27 #include <sys/socket.h>
29 #include <sys/signal.h>
31 #include <sys/resource.h>
34 /************************************************************************
36 * create_forking_server (create_forking_server)
38 * Called by an application to turn itself into a forking model
39 * server. Returns from this routine occur only in the forked
40 * children. The parent lives in this routine forever, waiting
41 * for incoming connection requests and doing the appropriate
44 * Children are expected to do their own cleanup, but this routine
45 * does do the work of reaping the resulting zombie processes.
50 * service-id identifies the port to be used for
51 * listening. Same rules as for
52 * create_listening_connection.
54 * validate-rtn pointer to a function to be called to
55 * validate the incoming client. Should
56 * return TRUE if client is acceptable,
57 * else false. If this is NULL, all clients
63 * Children created by this routine inherit the global variables
64 * gdb_sockaddr_of_client, which is of type sockaddr_in and
65 * gdb_socklen, which is the returned length of the sockaddr.
66 * These are the Berkeley identifiers of the clients as accepted.
67 * Use of this interface is non-portable to other than Berkeley
70 * The client's request tuple may be found in gdb_client_tuple.
72 ************************************************************************/
76 create_forking_server(service, validate)
80 void start_accepting_client();
81 CONNECTION incoming; /* listen for incoming */
83 CONNECTION client = NULL; /* connection to client */
85 OPERATION listenop; /* used to asynchronously */
86 /* listen for a child */
87 /* connection request */
90 /*----------------------------------------------------------*/
92 /* Set up parent execution environment
94 /*----------------------------------------------------------*/
96 g_do_signals(); /* set up signal handling */
98 incoming = create_listening_connection(service);
99 if (incoming == NULL || connection_status(incoming) != CON_UP)
100 GDB_GIVEUP("create_forking_server: can't create listening connection")
102 /*----------------------------------------------------------*/
104 /* Repeatedly listen for incoming
106 /*----------------------------------------------------------*/
108 listenop = create_operation();
110 gdb_socklen = sizeof(gdb_sockaddr_of_client);
112 (void) start_accepting_client(incoming, listenop, &client,
113 gdb_sockaddr_of_client, &gdb_socklen,
115 if(complete_operation(listenop) != OP_COMPLETE ||
117 gdb_perror("GDB create_forking_server: failed to accept client");
118 reset_operation(listenop);
119 (void) sever_connection(client);
125 * Call the validate routine, if it fails,
128 if (validate != NULL && !(*validate)()) {
129 reset_operation(listenop);
130 start_replying_to_client(listenop, client,
132 (void) complete_operation(listenop);
133 reset_operation(listenop);
134 (void) sever_connection(client);
138 * Create the child for this client
140 if ((gdb_Debug & GDB_NOFORK) || fork() == 0) {
142 * This is the child, or we're in noforking
145 reset_operation(listenop);
146 start_replying_to_client(listenop, client,
147 GDB_ACCEPTED, "","");
148 if (complete_operation(listenop) != OP_COMPLETE)
150 return client; /* return to application */
154 * Still in the parent
156 (void) sever_connection(client);
157 reset_operation(listenop);
161 /************************************************************************/
165 /* Called on SIGCHILD to reap all dead children.
167 /************************************************************************/
180 extern char *sys_siglist[];
183 while (waitpid(-1, &status, WNOHANG) >0);
185 while (wait3(&status, WNOHANG, (struct rusage *)0) >0);
189 /************************************************************************/
193 /* Set up signal handling for a forking server.
195 /************************************************************************/
201 struct sigaction act;
203 act.sa_handler = gdb_reaper;
204 sigemptyset(&act.sa_mask);
206 (void) sigaction(SIGCHLD, &act, (struct sigaction *)0);
208 (void) signal(SIGCHLD, gdb_reaper);