* Europagate, 1995
*
* $Log: monitor.c,v $
- * Revision 1.3 1995/05/02 07:20:10 adam
+ * Revision 1.4 1995/05/02 15:26:00 adam
+ * Monitor observes death of child (email kernel). The number
+ * of simultanous processes is controlled now. Email requests are
+ * queued if necessary. This scheme should only be forced if no kernels
+ * are idle.
+ *
+ * Revision 1.3 1995/05/02 07:20:10 adam
* Use pid of exited child to close fifos.
*
* Revision 1.2 1995/05/01 16:26:57 adam
#include <sys/wait.h>
#include <gw-log.h>
-#include <gw-log.h>
+#include <gw-res.h>
#include <gip.h>
#include <strqueue.h>
#include <lgets.h>
#define LINE_MAX 1024
+#define MONITOR_FIFO_S "fifo.s"
+#define MONITOR_FIFO_C "fifo.c"
+
static char *module = "monitor";
static jmp_buf retry_jmp;
+static GwRes monitor_res = NULL;
+static int no_process = 0;
+static int max_process = 1;
+static int got_sighup = 0;
+static int got_term = 0;
+const char *default_res = "default.res";
+
+static void reread_resources (void)
+{
+ if (monitor_res)
+ gw_res_close (monitor_res);
+ monitor_res = gw_res_init ();
+ if (gw_res_merge (monitor_res, default_res))
+ {
+ gw_log (GW_LOG_WARN, module, "Couldn't read resource file %s",
+ default_res);
+ exit (1);
+ }
+ max_process = atoi (gw_res_get (monitor_res, "gw.max.process", "10"));
+}
+
struct ke_info {
pid_t pid;
int id;
(*kip)->next = NULL;
(*kip)->id = id;
(*kip)->gip = NULL;
- if (!((*kip)->queue = str_queue_mk ()))
- {
- gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, module, "str_queue_mk");
- exit (1);
- }
+ (*kip)->queue = NULL;
return *kip;
}
-void ke_info_del (void)
+static void ke_info_del (void)
{
struct ke_info *ki;
free (ki);
}
-static void catchchild (int num)
+static void catch_child (int num)
{
pid_t pid;
struct ke_info *ki;
while ((pid=waitpid (-1, 0, WNOHANG)) > 0)
+ {
for (ki = ke_info_list; ki; ki = ki->next)
if (ki->pid == pid)
- {
- gw_log (GW_LOG_DEBUG, module, "Close of %d", ki->id);
- if (ki->gip)
- {
- gipc_close (ki->gip);
- gipc_destroy (ki->gip);
- ki->gip = NULL;
- }
- }
- signal (SIGCHLD, catchchild);
+ ki->pid = -1;
+ --no_process;
+ }
+ signal (SIGCHLD, catch_child);
+}
+
+static void catch_hup (int num)
+{
+ got_sighup = 1;
+ signal (SIGHUP, catch_hup);
+}
+
+static void catch_term (int num)
+{
+ got_term = 1;
+ signal (SIGTERM, catch_term);
}
static void pipe_handle (int dummy)
return pid;
}
-static void deliver (int argc, char **argv, int id, struct str_queue *queue,
- GIP *gip, pid_t *pidp)
+static int deliver (int argc, char **argv, int id, struct str_queue *queue,
+ GIP *gip, pid_t *pidp, int dont_exec)
{
int pass = 0;
int r;
setjmp (retry_jmp);
++pass;
if (pass == 1)
+ {
+ gipc_close (*gip);
r = gipc_open (*gip, fifo_server_name, 0);
+ }
else if (pass == 2)
{
pid_t pid;
+ if (dont_exec)
+ {
+ signal (SIGPIPE, oldsig);
+ return 0;
+ }
mknod (fifo_server_name, S_IFIFO|0666, 0);
pid = start_kernel (argc, argv, id);
if (pidp)
}
else
{
+ signal (SIGPIPE, oldsig);
gw_log (GW_LOG_WARN, module, "Cannot start kernel");
- return;
+ return 0;
}
if (r < 0)
{
else
{
gw_log (GW_LOG_WARN|GW_LOG_ERRNO, module, "gipc_open");
- return;
}
}
index = 0;
while ((msg = str_queue_get (queue, index++)))
gip_wline (*gip, msg);
signal (SIGPIPE, oldsig);
+ return pass;
}
static void monitor_events (int argc, char **argv)
char line_buf[1024];
fd_set set_r;
char command[128], *cp;
- int no_process = 0;
- int max_process = 4;
- gip_m = gips_initialize ("fifo.s");
- r = gips_open (gip_m, "fifo.c");
+ gip_m = gips_initialize (MONITOR_FIFO_S);
+ r = gips_open (gip_m, MONITOR_FIFO_C);
gip_m_fd = gip_infileno (gip_m);
- open ("fifo.s", O_WRONLY);
+ open (MONITOR_FIFO_S, O_WRONLY);
while (1)
{
int fd_max;
struct ke_info *ki;
- while (1)
+ while (1)
{
- FD_ZERO (&set_r);
- FD_SET (gip_m_fd, &set_r);
- gw_log (GW_LOG_DEBUG, module, "set r %d", gip_m_fd);
- fd_max = gip_m_fd;
-
+ if (got_sighup)
+ {
+ gw_log (GW_LOG_STAT, module, "Got SIGHUP. Reading resources");
+ reread_resources ();
+ got_sighup = 0;
+ }
+ if (got_term)
+ {
+ gw_log (GW_LOG_STAT, module, "Got SIGTERM. Exiting...");
+ unlink (MONITOR_FIFO_S);
+ unlink (MONITOR_FIFO_C);
+ exit (0);
+ }
for (ki = ke_info_list; ki; ki = ki->next)
{
if (!ki->queue)
continue;
gw_log (GW_LOG_DEBUG, module, "Transfer mail to %d", ki->id);
- deliver (argc, argv, ki->id, ki->queue, &ki->gip, &ki->pid);
- str_queue_rm (&ki->queue);
+ r = deliver (argc, argv, ki->id, ki->queue, &ki->gip, &ki->pid,
+ no_process >= max_process);
+ if (r == 2)
+ ++no_process;
+ if (r == 1 || r == 2)
+ str_queue_rm (&ki->queue);
}
+ FD_ZERO (&set_r);
+ FD_SET (gip_m_fd, &set_r);
+ gw_log (GW_LOG_DEBUG, module, "set gip_m_fd %d", gip_m_fd);
+ fd_max = gip_m_fd;
+
for (ki = ke_info_list; ki; ki = ki->next)
{
int fd;
- if (ki->gip && (fd = gip_infileno (ki->gip)) != -1)
+ if (ki->gip)
{
- gw_log (GW_LOG_DEBUG, module, "set r %d", fd);
- FD_SET (fd, &set_r);
- if (fd > fd_max)
- fd_max = fd;
+ if (ki->pid == -1)
+ {
+ gw_log (GW_LOG_DEBUG, module, "Close of %d", ki->id);
+ gipc_close (ki->gip);
+ gipc_destroy (ki->gip);
+ ki->gip = NULL;
+ }
+ else if ((fd = gip_infileno (ki->gip)) != -1)
+ {
+ gw_log (GW_LOG_DEBUG, module, "set fd %d", fd);
+ FD_SET (fd, &set_r);
+ if (fd > fd_max)
+ fd_max = fd;
+ }
}
}
+ gw_log (GW_LOG_DEBUG, module, "Cur/Max processes %d/%d",
+ no_process, max_process);
gw_log (GW_LOG_DEBUG, module, "IPC select");
r = select (fd_max+1, &set_r, NULL, NULL, NULL);
if (r != -1)
}
}
}
-
gw_log (GW_LOG_DEBUG, module, "Testing gip_m_fd %d", gip_m_fd);
if (FD_ISSET (gip_m_fd, &set_r))
{
new_k = ke_info_add (id);
gw_log (GW_LOG_DEBUG, module, "Incoming mail %d", id);
+
+ if (!new_k->queue)
+ {
+ if (!(new_k->queue = str_queue_mk ()))
+ {
+ gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, module,
+ "str_queue_mk");
+ exit (1);
+ }
+ }
str_queue_enq (new_k->queue, "mail\n");
while (lgets (line_buf, sizeof(line_buf)-1, gip_m_fd))
str_queue_enq (new_k->queue, line_buf);
int main (int argc, char **argv)
{
+ int argno = 0;
+
gw_log_init (*argv);
- gw_log_level (GW_LOG_ALL);
- signal (SIGCHLD, catchchild);
+ while (++argno < argc)
+ {
+ if (argv[argno][0] == '-')
+ {
+ switch (argv[argno][1])
+ {
+ case 'H':
+ fprintf (stderr, "monitor [option..] [resource]\n");
+ fprintf (stderr, "If no resource file is given");
+ fprintf (stderr, " default.res is used\n");
+ fprintf (stderr, "Options are transferred to kernel\n");
+ exit (1);
+ case 'd':
+ gw_log_level (GW_LOG_ALL & ~RES_DEBUG);
+ break;
+ case 'D':
+ gw_log_level (GW_LOG_ALL);
+ break;
+ }
+ }
+ else
+ default_res = argv[argno];
+ }
+ reread_resources ();
+ signal (SIGCHLD, catch_child);
+ signal (SIGHUP, catch_hup);
+ signal (SIGTERM, catch_term);
#if 0
gw_log_file (GW_LOG_ALL, "monitor.log");
#endif
monitor_events (argc, argv);
exit (0);
}
-
-
-
-