]> git.neil.brown.name Git - metad.git/blob - mainloop.c
Assorted reformating
[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 static fd_set wait_for, are_ready;
25 static fd_set write_on, can_write;
26 static 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