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
38 /* For copying and distribution information, please see
39 /* the file <mit-copyright.h>.
41 /************************************************************************/
43 #include <mit-copyright.h>
45 #include <sys/types.h>
47 #include <sys/socket.h>
49 #include <sys/signal.h>
51 #include <sys/resource.h>
53 /************************************************************************/
55 /* create_forking_server (create_forking_server)
57 /* Called by an application to turn itself into a forking model
58 /* server. Returns from this routine occur only in the forked
59 /* children. The parent lives in this routine forever, waiting
60 /* for incoming connection requests and doing the appropriate
63 /* Children are expected to do their own cleanup, but this routine
64 /* does do the work of reaping the resulting zombie processes.
69 /* service-id identifies the port to be used for
70 /* listening. Same rules as for
71 /* create_listening_connection.
73 /* validate-rtn pointer to a function to be called to
74 /* validate the incoming client. Should
75 /* return TRUE if client is acceptable,
76 /* else false. If this is NULL, all clients
82 /* Children created by this routine inherit the global variables
83 /* gdb_sockaddr_of_client, which is of type sockaddr_in and
84 /* gdb_socklen, which is the returned length of the sockaddr.
85 /* These are the Berkeley identifiers of the clients as accepted.
86 /* Use of this interface is non-portable to other than Berkeley
89 /* The client's request tuple may be found in gdb_client_tuple.
91 /************************************************************************/
95 create_forking_server(service, validate)
100 CONNECTION incoming; /* listen for incoming */
102 CONNECTION client = NULL; /* connection to client */
103 /* is created here */
104 OPERATION listenop; /* used to asynchronously */
105 /* listen for a child */
106 /* connection request */
109 /*----------------------------------------------------------*/
111 /* Set up parent execution environment
113 /*----------------------------------------------------------*/
115 g_do_signals(); /* set up signal handling */
117 incoming = create_listening_connection(service);
118 if (incoming == NULL)
119 GDB_GIVEUP("create_forking_server: can't create listening connection")
121 /*----------------------------------------------------------*/
123 /* Repeatedly listen for incoming
125 /*----------------------------------------------------------*/
127 listenop = create_operation();
129 gdb_socklen = sizeof(gdb_sockaddr_of_client);
131 (void) start_accepting_client(incoming, listenop, &client,
132 gdb_sockaddr_of_client, &gdb_socklen,
134 if(complete_operation(listenop) != OP_COMPLETE ||
136 GDB_GIVEUP("create_forking_server: failed to accept client")
140 * Call the validate routine, if it fails,
143 if (validate != NULL && !(*validate)()) {
144 reset_operation(listenop);
145 start_replying_to_client(listenop, client,
147 (void) complete_operation(listenop);
148 reset_operation(listenop);
149 (void) sever_connection(client);
153 * Create the child for this client
155 if ((gdb_Debug & GDB_NOFORK) || fork() == 0) {
157 * This is the child, or we're in noforking
160 reset_operation(listenop);
161 start_replying_to_client(listenop, client,
162 GDB_ACCEPTED, "","");
163 if (complete_operation(listenop) != OP_COMPLETE)
165 return client; /* return to application */
169 * Still in the parent
171 (void) sever_connection(client);
172 reset_operation(listenop);
176 /************************************************************************/
180 /* Called on SIGCHILD to reap all dead children.
182 /************************************************************************/
187 extern char *sys_siglist[];
189 while (wait3(&status, WNOHANG, (struct rusage *)0) >0) {
191 if (WIFEXITED(status)) {
192 if (status.w_retcode)
193 printf("exited with code %d\n",
196 if (WIFSIGNALED(status)) {
197 printf("exited on %s signal%s\n",
198 sys_siglist[status.w_termsig],
199 (status.w_coredump?"; core dumped":0));
205 /************************************************************************/
209 /* Set up signal handling for a forking server.
211 /************************************************************************/
216 (void) signal(SIGCHLD, gdb_reaper);