7 static char *rcsid_gdb_fserv_c = "$Header$";
30 /************************************************************************/
34 /* GDB - Routines to implement forking servers.
36 /* Author: Noah Mendelsohn
37 /* Copyright: 1986 MIT Project Athena
39 /************************************************************************/
42 #include <sys/types.h>
44 #include <sys/socket.h>
46 #include <sys/signal.h>
48 #include <sys/resource.h>
50 /************************************************************************/
52 /* create_forking_server (create_forking_server)
54 /* Called by an application to turn itself into a forking model
55 /* server. Returns from this routine occur only in the forked
56 /* children. The parent lives in this routine forever, waiting
57 /* for incoming connection requests and doing the appropriate
60 /* Children are expected to do their own cleanup, but this routine
61 /* does do the work of reaping the resulting zombie processes.
66 /* service-id identifies the port to be used for
67 /* listening. Same rules as for
68 /* create_listening_connection.
70 /* validate-rtn pointer to a function to be called to
71 /* validate the incoming client. Should
72 /* return TRUE if client is acceptable,
73 /* else false. If this is NULL, all clients
79 /* Children created by this routine inherit the global variables
80 /* gdb_sockaddr_of_client, which is of type sockaddr_in and
81 /* gdb_socklen, which is the returned length of the sockaddr.
82 /* These are the Berkeley identifiers of the clients as accepted.
83 /* Use of this interface is non-portable to other than Berkeley
86 /* The client's request tuple may be found in gdb_client_tuple.
88 /************************************************************************/
92 create_forking_server(service, validate)
97 CONNECTION incoming; /* listen for incoming */
99 CONNECTION client = NULL; /* connection to client */
100 /* is created here */
101 OPERATION listenop; /* used to asynchronously */
102 /* listen for a child */
103 /* connection request */
106 /*----------------------------------------------------------*/
108 /* Set up parent execution environment
110 /*----------------------------------------------------------*/
112 g_do_signals(); /* set up signal handling */
114 incoming = create_listening_connection(service);
115 if (incoming == NULL)
116 GDB_GIVEUP("create_forking_server: can't create listening connection")
118 /*----------------------------------------------------------*/
120 /* Repeatedly listen for incoming
122 /*----------------------------------------------------------*/
124 listenop = create_operation();
126 gdb_socklen = sizeof(gdb_sockaddr_of_client);
128 (void) start_accepting_client(incoming, listenop, &client,
129 gdb_sockaddr_of_client, &gdb_socklen,
131 if(complete_operation(listenop) != OP_COMPLETE ||
133 GDB_GIVEUP("create_forking_server: failed to accept client")
137 * Call the validate routine, if it fails,
140 if (validate != NULL && !(*validate)()) {
141 reset_operation(listenop);
142 start_replying_to_client(listenop, client,
144 (void) complete_operation(listenop);
145 reset_operation(listenop);
146 (void) sever_connection(client);
150 * Create the child for this client
152 if ((gdb_Debug & GDB_NOFORK) || fork() == 0) {
154 * This is the child, or we're in noforking
157 reset_operation(listenop);
158 start_replying_to_client(listenop, client,
159 GDB_ACCEPTED, "","");
160 if (complete_operation(listenop) != OP_COMPLETE)
162 return client; /* return to application */
166 * Still in the parent
168 (void) sever_connection(client);
169 reset_operation(listenop);
173 /************************************************************************/
177 /* Called on SIGCHILD to reap all dead children.
179 /************************************************************************/
184 extern char *sys_siglist[];
186 while (wait3(&status, WNOHANG, (struct rusage *)0) >0) {
188 if (WIFEXITED(status)) {
189 if (status.w_retcode)
190 printf("exited with code %d\n",
193 if (WIFSIGNALED(status)) {
194 printf("exited on %s signal%s\n",
195 sys_siglist[status.w_termsig],
196 (status.w_coredump?"; core dumped":0));
202 /************************************************************************/
206 /* Set up signal handling for a forking server.
208 /************************************************************************/
213 (void) signal(SIGCHLD, gdb_reaper);