]> git.neil.brown.name Git - metad.git/blob - mainloop.c
Create Makefile and get it to compile with -Wall
[metad.git] / mainloop.c
1
2
3 #include        "metad.h"
4 #include        <signal.h>
5 #include        "skip.h"
6 #include        <sys/time.h>
7
8 /*
9  * main loop of metad
10  * wait for read-select on some sockets, or for time to pass
11  * or for a process to exit.
12  * when one of these happens, we check with each service to see
13  * if it wants to do something.
14  *
15  * services ask to do something with
16  *  listenon(socket)
17  *  waituntil(time)
18  * and can check is a socket is read with
19  *  readyon(socket)
20  *
21  */
22
23
24 fd_set wait_for, are_ready;
25 fd_set write_on, can_write;
26 time_t when_wake;
27
28 void listenon(int socket)
29 {
30     FD_SET(socket, &wait_for);
31 }
32
33 int readyon(int socket)
34 {
35     return FD_ISSET(socket, &are_ready);
36 }
37
38 void writeon(int socket)
39 {
40     FD_SET(socket, &write_on);
41 }
42
43
44
45 int canwrite(int socket)
46 {
47     return FD_ISSET(socket, &can_write);
48 }
49
50 void waituntil(time_t when)
51 {
52     if (when_wake == 0 || when_wake > when) when_wake = when;
53 }
54
55 static struct
56 {
57     pid_t pid;
58     int status;
59     time_t time;
60 } saved_pids[20] = { { 0 } };
61
62 static struct timeval select_tv;
63 static void collectchild()
64 {
65     pid_t pid;
66     int status;
67
68     if ((pid = waitpid(-1, &status, WNOHANG)) > 0)
69     {
70         int i;
71         for (i=0; i<20 ; i++)
72             if (saved_pids[i].pid == 0)
73             {
74                 saved_pids[i].pid = pid;
75                 saved_pids[i].status = status;
76                 time(&saved_pids[i].time);
77                 break;
78             }
79     }
80     select_tv.tv_usec = 0;
81     select_tv.tv_sec = 0;
82 }
83
84 int is_saved_pid(pid_t pid)
85 {
86         int i;
87         for (i=0; i<20; i++)
88                 if (saved_pids[i].pid == pid)
89                         return 1;
90         return 0;
91 }
92
93 void main_loop()
94 {
95     struct sigaction sa;
96     sigset_t ss;
97     sa.sa_handler = collectchild;
98     sa.sa_flags = 0;
99     sigemptyset(&ss);
100     sigaddset(&ss, SIGCLD);
101     sa.sa_mask = ss;
102     sigaction(SIGCLD, &sa, NULL);
103
104     FD_ZERO(&are_ready);
105     FD_ZERO(&can_write);
106     while (1)
107     {
108         service_t *svp;
109         int i;
110         FD_ZERO(&wait_for);
111         FD_ZERO(&write_on);
112         when_wake = time(0)+5*60; /* always wakeup every 5minutes to look around... */
113         collectchild(); /* incase signal was missed */
114
115         for (i=0 ; i<20 ; i++)
116             if (saved_pids[i].pid)
117             {
118                 proc_t *pp;
119                 pp = skip_search(allprocs, &saved_pids[i].pid);
120                 if (pp)
121                 {
122                     (*pp)->status = saved_pids[i].status;
123                     (*pp)->exit_time = saved_pids[i].time;;
124                     select_tv.tv_sec = 0;
125                     logmsg(LOG_INFO, "process %d (%s) exited - status 0x%04x", saved_pids[i].pid, (*pp)->service->service, (*pp)->status);
126                 } else 
127                     logmsg(LOG_INFO, "process %d exited - status 0x%04x", saved_pids[i].pid, saved_pids[i].status);
128                 saved_pids[i].pid = 0;
129
130             }
131
132         for (svp = skip_first(services) ; svp ; svp = skip_next(svp))
133             check_service(*svp);
134         check_control();
135         are_ready = wait_for;
136         can_write = write_on;
137             
138         if (when_wake)
139         {
140             time_t now;
141             time(&now);
142             select_tv.tv_sec = when_wake - now;
143             select_tv.tv_usec = 0;
144             if (when_wake < now) select_tv.tv_sec = 0;
145         }
146         else
147         {
148             select_tv.tv_sec = 100000;
149             select_tv.tv_usec = 0;
150         }
151         if (select(FD_SETSIZE, &are_ready, &can_write, NULL, &select_tv) <= 0)
152         {
153             FD_ZERO(&are_ready);
154             FD_ZERO(&can_write);
155         }
156     }
157 }
158