]> andersk Git - moira.git/blob - gdb/gdb_fserv.c
Diane Delgado's changes for a fixed table-locking order
[moira.git] / gdb / gdb_fserv.c
1 /*
2  * $Header$
3  */
4
5 #ifndef lint
6 static char *rcsid_gdb_fserv_c = "$Header$";
7 #endif  lint
8
9
10 /************************************************************************
11  *      
12  *                         gdb_fserv.c
13  *      
14  *            GDB - Routines to implement forking servers.
15  *      
16  *      Author: Noah Mendelsohn
17  *      Copyright: 1986 MIT Project Athena 
18  *              For copying and distribution information, please see
19  *              the file <mit-copyright.h>.
20  *      
21  ************************************************************************/
22
23 #include <mit-copyright.h>
24 #include <stdio.h>
25 #include <sys/types.h>
26 #include <sys/uio.h>
27 #include <sys/socket.h>
28 #include <sys/wait.h>
29 #include <sys/signal.h>
30 #include "gdb.h"
31 #include <sys/resource.h>
32
33
34 /************************************************************************
35  *      
36  *                      create_forking_server (create_forking_server)
37  *      
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
42  *      forking.
43  *      
44  *      Children are expected to do their own cleanup, but this routine
45  *      does do the work of reaping the resulting zombie processes.
46  *      
47  *      ARGUMENTS:
48  *      ----------
49  *      
50  *              service-id      identifies the port to be used for
51  *                              listening.  Same rules as for
52  *                              create_listening_connection.
53  *      
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
58  *                              are accepted.
59  *      
60  *      GLOBAL VARIABLES
61  *      ----------------
62  *      
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 
68  *      systems.
69  *      
70  *      The client's request tuple may be found in gdb_client_tuple.
71  *      
72  ************************************************************************/
73
74
75 CONNECTION
76 create_forking_server(service, validate)
77 char *service;
78 int (*validate)();
79 {
80         void start_accepting_client();
81         CONNECTION incoming;                    /* listen for incoming */
82                                                 /* children here */
83         CONNECTION client = NULL;               /* connection to client */
84                                                 /* is created here */
85         OPERATION listenop;                     /* used to asynchronously */
86                                                 /* listen for a child */
87                                                 /* connection request */
88         GDB_INIT_CHECK
89
90         /*----------------------------------------------------------*/
91         /*      
92         /*      Set up parent execution environment
93         /*      
94         /*----------------------------------------------------------*/
95
96         g_do_signals();                         /* set up signal handling */
97
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")
101
102         /*----------------------------------------------------------*/
103         /*      
104         /*      Repeatedly listen for incoming
105         /*      
106         /*----------------------------------------------------------*/
107
108         listenop = create_operation();
109         while (TRUE) {
110                 gdb_socklen = sizeof(gdb_sockaddr_of_client);
111                 client = NULL;
112                 (void) start_accepting_client(incoming, listenop, &client, 
113                                        gdb_sockaddr_of_client, &gdb_socklen,
114                                        &gdb_client_tuple);
115                 if(complete_operation(listenop) != OP_COMPLETE ||
116                    client == NULL) {
117                     gdb_perror("GDB create_forking_server: failed to accept client");
118                     reset_operation(listenop);
119                     (void) sever_connection(client);
120                     continue;
121                   }
122                 
123
124                 /*
125                  * Call the validate routine, if it fails, 
126                  * refuse the client.
127                  */
128                 if (validate != NULL && !(*validate)()) {
129                         reset_operation(listenop);
130                         start_replying_to_client(listenop, client, 
131                                                  GDB_REFUSED, "","");
132                         (void) complete_operation(listenop); 
133                         reset_operation(listenop);
134                         (void) sever_connection(client);
135                         continue;                       
136                 }
137                 /*
138                  * Create  the child for this client
139                  */
140                 if ((gdb_Debug & GDB_NOFORK) || fork() == 0) {
141                        /*
142                         * This is the child, or we're in noforking
143                         * debug mode.
144                         */
145                         reset_operation(listenop);
146                         start_replying_to_client(listenop, client, 
147                                                  GDB_ACCEPTED, "","");
148                         if (complete_operation(listenop) != OP_COMPLETE) 
149                                 exit(8);
150                         return client;          /* return to application */
151                                                 /* program */
152                 }
153                /*
154                 * Still in the parent
155                 */
156                 (void) sever_connection(client);
157                 reset_operation(listenop);
158         }
159 }
160 \f
161 /************************************************************************/
162 /*      
163 /*                              gdb_reaper
164 /*      
165 /*      Called on SIGCHILD to reap all dead children.
166 /*      
167 /************************************************************************/
168 #ifndef POSIX
169 int
170 #else
171 void
172 #endif
173 gdb_reaper()
174 {
175 #ifdef POSIX
176         int status;
177 #else
178         union wait status;
179 #endif
180         extern char *sys_siglist[];
181        
182 #ifdef POSIX
183         while (waitpid(-1, &status, WNOHANG) >0);
184 #else
185         while (wait3(&status, WNOHANG, (struct rusage *)0) >0);
186 #endif
187 }
188 \f
189 /************************************************************************/
190 /*      
191 /*                              g_do_signals
192 /*      
193 /*      Set up signal handling for a forking server.
194 /*      
195 /************************************************************************/
196
197 int
198 g_do_signals()
199 {
200 #ifdef POSIX
201     struct sigaction act;
202
203     act.sa_handler = gdb_reaper;
204     sigemptyset(&act.sa_mask);
205     act.sa_flags = 0;
206     (void) sigaction(SIGCHLD, &act, (struct sigaction *)0);
207 #else /* sun */
208     (void) signal(SIGCHLD, gdb_reaper);
209 #endif 
210 }
This page took 1.775691 seconds and 5 git commands to generate.