1 /* Gateway Resource Monitor
5 * Revision 1.4 1995/05/02 15:26:00 adam
6 * Monitor observes death of child (email kernel). The number
7 * of simultanous processes is controlled now. Email requests are
8 * queued if necessary. This scheme should only be forced if no kernels
11 * Revision 1.3 1995/05/02 07:20:10 adam
12 * Use pid of exited child to close fifos.
14 * Revision 1.2 1995/05/01 16:26:57 adam
15 * More work on resource monitor.
17 * Revision 1.1 1995/05/01 12:43:36 adam
18 * First work on resource monitor program.
34 #include <sys/types.h>
46 #define MONITOR_FIFO_S "fifo.s"
47 #define MONITOR_FIFO_C "fifo.c"
49 static char *module = "monitor";
50 static jmp_buf retry_jmp;
52 static GwRes monitor_res = NULL;
53 static int no_process = 0;
54 static int max_process = 1;
55 static int got_sighup = 0;
56 static int got_term = 0;
57 const char *default_res = "default.res";
59 static void reread_resources (void)
62 gw_res_close (monitor_res);
63 monitor_res = gw_res_init ();
64 if (gw_res_merge (monitor_res, default_res))
66 gw_log (GW_LOG_WARN, module, "Couldn't read resource file %s",
70 max_process = atoi (gw_res_get (monitor_res, "gw.max.process", "10"));
77 struct str_queue *queue;
81 struct ke_info *ke_info_list = NULL;
83 struct ke_info *ke_info_add (int id)
87 for (kip = &ke_info_list; *kip; kip= &(*kip)->next)
90 *kip = malloc (sizeof(**kip));
99 static void ke_info_del (void)
103 assert (ke_info_list);
105 str_queue_rm (&ki->queue);
106 ke_info_list = ki->next;
110 static void catch_child (int num)
115 while ((pid=waitpid (-1, 0, WNOHANG)) > 0)
117 for (ki = ke_info_list; ki; ki = ki->next)
122 signal (SIGCHLD, catch_child);
125 static void catch_hup (int num)
128 signal (SIGHUP, catch_hup);
131 static void catch_term (int num)
134 signal (SIGTERM, catch_term);
137 static void pipe_handle (int dummy)
139 longjmp (retry_jmp, 1);
142 static pid_t start_kernel (int argc, char **argv, int id)
147 char userid_option[20];
149 argv_p = malloc (sizeof(*argv_p)*(argc+2));
152 gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, module, "malloc fail");
155 argv_p[0] = "kernel";
156 for (i = 1; i<argc; i++)
158 sprintf (userid_option, "-i%d", id);
159 argv_p[i++] = userid_option;
162 gw_log (GW_LOG_DEBUG, module, "Starting kernel");
166 gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, module, "fork");
171 execv ("kernel", argv_p);
172 gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, module, "execvp");
178 static int deliver (int argc, char **argv, int id, struct str_queue *queue,
179 GIP *gip, pid_t *pidp, int dont_exec)
184 char fifo_server_name[128];
185 char fifo_client_name[128];
189 sprintf (fifo_server_name, "fifo.s.%d", id);
190 sprintf (fifo_client_name, "fifo.c.%d", id);
194 *gip = gipc_initialize (fifo_client_name);
196 oldsig = signal (SIGPIPE, pipe_handle);
202 r = gipc_open (*gip, fifo_server_name, 0);
210 signal (SIGPIPE, oldsig);
213 mknod (fifo_server_name, S_IFIFO|0666, 0);
214 pid = start_kernel (argc, argv, id);
217 r = gipc_open (*gip, fifo_server_name, 1);
221 signal (SIGPIPE, oldsig);
222 gw_log (GW_LOG_WARN, module, "Cannot start kernel");
229 gw_log (GW_LOG_DEBUG|GW_LOG_ERRNO, module, "r==-2");
230 longjmp (retry_jmp, 1);
234 gw_log (GW_LOG_DEBUG|GW_LOG_ERRNO, module, "r==-1");
235 longjmp (retry_jmp, 1);
239 gw_log (GW_LOG_WARN|GW_LOG_ERRNO, module, "gipc_open");
243 while ((msg = str_queue_get (queue, index++)))
244 gip_wline (*gip, msg);
245 signal (SIGPIPE, oldsig);
249 static void monitor_events (int argc, char **argv)
255 char command[128], *cp;
257 gip_m = gips_initialize (MONITOR_FIFO_S);
258 r = gips_open (gip_m, MONITOR_FIFO_C);
259 gip_m_fd = gip_infileno (gip_m);
260 open (MONITOR_FIFO_S, O_WRONLY);
271 gw_log (GW_LOG_STAT, module, "Got SIGHUP. Reading resources");
277 gw_log (GW_LOG_STAT, module, "Got SIGTERM. Exiting...");
278 unlink (MONITOR_FIFO_S);
279 unlink (MONITOR_FIFO_C);
282 for (ki = ke_info_list; ki; ki = ki->next)
286 gw_log (GW_LOG_DEBUG, module, "Transfer mail to %d", ki->id);
287 r = deliver (argc, argv, ki->id, ki->queue, &ki->gip, &ki->pid,
288 no_process >= max_process);
291 if (r == 1 || r == 2)
292 str_queue_rm (&ki->queue);
295 FD_SET (gip_m_fd, &set_r);
296 gw_log (GW_LOG_DEBUG, module, "set gip_m_fd %d", gip_m_fd);
299 for (ki = ke_info_list; ki; ki = ki->next)
306 gw_log (GW_LOG_DEBUG, module, "Close of %d", ki->id);
307 gipc_close (ki->gip);
308 gipc_destroy (ki->gip);
311 else if ((fd = gip_infileno (ki->gip)) != -1)
313 gw_log (GW_LOG_DEBUG, module, "set fd %d", fd);
320 gw_log (GW_LOG_DEBUG, module, "Cur/Max processes %d/%d",
321 no_process, max_process);
322 gw_log (GW_LOG_DEBUG, module, "IPC select");
323 r = select (fd_max+1, &set_r, NULL, NULL, NULL);
328 gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, module, "select");
331 gw_log (GW_LOG_DEBUG|GW_LOG_ERRNO, module, "select");
333 gw_log (GW_LOG_DEBUG, module, "Testing ke_info_list");
334 for (ki = ke_info_list; ki; ki = ki->next)
337 if (ki->gip && (fd = gip_infileno (ki->gip)) != -1)
339 gw_log (GW_LOG_DEBUG, module, "Test of %d", fd);
340 if (FD_ISSET (fd, &set_r))
342 if (lgets (line_buf, sizeof(line_buf)-1, fd))
344 gw_log (GW_LOG_DEBUG, module, "IPC: %s", line_buf);
348 gw_log (GW_LOG_DEBUG, module, "Close of %d", ki->id);
349 gipc_close (ki->gip);
350 gipc_destroy (ki->gip);
356 gw_log (GW_LOG_DEBUG, module, "Testing gip_m_fd %d", gip_m_fd);
357 if (FD_ISSET (gip_m_fd, &set_r))
359 gw_log (GW_LOG_DEBUG, module, "Reading from %d", gip_m_fd);
360 if (!(lgets (command, sizeof(command)-1, gip_m_fd)))
362 gw_log (GW_LOG_FATAL, module, "Unexpected close");
365 gw_log (GW_LOG_DEBUG, module, "Done");
366 if ((cp = strchr (command, '\n')))
368 gw_log (GW_LOG_DEBUG, module, "IPC: %s", command);
369 if (!memcmp (command, "eti ", 4))
371 int id = atoi (command+4);
372 struct ke_info *new_k;
374 new_k = ke_info_add (id);
375 gw_log (GW_LOG_DEBUG, module, "Incoming mail %d", id);
379 if (!(new_k->queue = str_queue_mk ()))
381 gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, module,
386 str_queue_enq (new_k->queue, "mail\n");
387 while (lgets (line_buf, sizeof(line_buf)-1, gip_m_fd))
388 str_queue_enq (new_k->queue, line_buf);
389 str_queue_enq (new_k->queue, "\001");
395 int main (int argc, char **argv)
400 while (++argno < argc)
402 if (argv[argno][0] == '-')
404 switch (argv[argno][1])
407 fprintf (stderr, "monitor [option..] [resource]\n");
408 fprintf (stderr, "If no resource file is given");
409 fprintf (stderr, " default.res is used\n");
410 fprintf (stderr, "Options are transferred to kernel\n");
413 gw_log_level (GW_LOG_ALL & ~RES_DEBUG);
416 gw_log_level (GW_LOG_ALL);
421 default_res = argv[argno];
424 signal (SIGCHLD, catch_child);
425 signal (SIGHUP, catch_hup);
426 signal (SIGTERM, catch_term);
428 gw_log_file (GW_LOG_ALL, "monitor.log");
430 monitor_events (argc, argv);