1 /* Reincarnation Server. This servers starts new system services and detects
2 * they are exiting. In case of errors, system services can be restarted.
3 * The RS server periodically checks the status of all registered services
4 * services to see whether they are still alive. The system services are
5 * expected to periodically send a heartbeat message.
8 * Jul 22, 2005 by Jorrit N. Herder
11 #include <minix/dmap.h>
12 #include <minix/endpoint.h>
13 #include "../../kernel/const.h"
14 #include "../../kernel/type.h"
16 /* Declare some local functions. */
17 FORWARD
_PROTOTYPE(void init_server
, (void) );
18 FORWARD
_PROTOTYPE(void sig_handler
, (void) );
19 FORWARD
_PROTOTYPE(void get_work
, (message
*m
) );
20 FORWARD
_PROTOTYPE(void reply
, (int whom
, message
*m_out
) );
22 /* Data buffers to retrieve info during initialization. */
23 PRIVATE
struct boot_image image
[NR_BOOT_PROCS
];
24 PUBLIC
struct dmap dmap
[NR_DEVICES
];
28 /*===========================================================================*
30 *===========================================================================*/
33 /* This is the main routine of this service. The main loop consists of
34 * three major activities: getting new work, processing the work, and
35 * sending the reply. The loop never terminates, unless a panic occurs.
37 message m
; /* request message */
38 int call_nr
, who_e
,who_p
; /* call number and caller */
39 int result
; /* result to return */
40 sigset_t sigset
; /* system signal set */
43 /* Initialize the server, then go to work. */
46 /* Main loop - get work and do it, forever. */
49 /* Wait for request message. */
52 who_p
= _ENDPOINT_P(who_e
);
53 if(who_p
< -NR_TASKS
|| who_p
>= NR_PROCS
)
54 panic("RS","message from bogus source", who_e
);
58 /* Now determine what to do. Three types of requests are expected:
59 * - Heartbeat messages (notifications from registered system services)
60 * - System notifications (POSIX signals or synchronous alarm)
61 * - User requests (control messages to manage system services)
64 /* Notification messages are control messages and do not need a reply.
65 * These include heartbeat messages and system notifications.
67 if (m
.m_type
& NOTIFY_MESSAGE
) {
70 do_period(&m
); /* check drivers status */
75 default: /* heartbeat notification */
76 if (rproc_ptr
[who_p
] != NULL
) /* mark heartbeat time */
77 rproc_ptr
[who_p
]->r_alive_tm
= m
.NOTIFY_TIMESTAMP
;
81 /* If this is not a notification message, it is a normal request.
82 * Handle the request and send a reply to the caller.
86 case RS_UP
: result
= do_up(&m
, FALSE
, 0); break;
87 case RS_UP_COPY
: result
= do_up(&m
, TRUE
, 0); break;
88 case RS_START
: result
= do_start(&m
); break;
89 case RS_DOWN
: result
= do_down(&m
); break;
90 case RS_REFRESH
: result
= do_refresh(&m
); break;
91 case RS_RESTART
: result
= do_restart(&m
); break;
92 case RS_SHUTDOWN
: result
= do_shutdown(&m
); break;
93 case GETSYSINFO
: result
= do_getsysinfo(&m
); break;
95 printf("Warning, RS got unexpected request %d from %d\n",
96 m
.m_type
, m
.m_source
);
100 /* Finally send reply message, unless disabled. */
101 if (result
!= EDONTREPLY
) {
110 /*===========================================================================*
112 *===========================================================================*/
113 PRIVATE
void init_server(void)
115 /* Initialize the reincarnation server. */
117 struct boot_image
*ip
;
120 /* Install signal handlers. Ask PM to transform signal into message. */
121 sa
.sa_handler
= SIG_MESS
;
122 sigemptyset(&sa
.sa_mask
);
124 if (sigaction(SIGCHLD
,&sa
,NULL
)<0) panic("RS","sigaction failed", errno
);
125 if (sigaction(SIGTERM
,&sa
,NULL
)<0) panic("RS","sigaction failed", errno
);
127 /* Initialize the system process table. Use the boot image from the kernel
128 * and the device map from the FS to gather all needed information.
130 if ((s
= sys_getimage(image
)) != OK
)
131 panic("RS","warning: couldn't get copy of image table", s
);
132 if ((s
= getsysinfo(FS_PROC_NR
, SI_DMAP_TAB
, dmap
)) < 0)
133 panic("RS","warning: couldn't get copy of dmap table", errno
);
136 /* Now initialize the table with the processes in the system image.
137 * Prepend /sbin/ to the binaries so that we can actually find them.
139 for (s
=0; s
< NR_BOOT_PROCS
; s
++) {
141 if (ip
->proc_nr
>= 0) {
142 rproc
[s
].r_flags
= RS_IN_USE
;
143 rproc
[s
].r_proc_nr_e
= ip
->endpoint
;
144 rproc
[s
].r_pid
= getnpid(ip
->proc_nr
);
145 for(t
=0; t
< NR_DEVICES
; t
++)
146 if (dmap
[t
].dmap_driver
== ip
->proc_nr
)
147 rproc
[s
].r_dev_nr
= t
;
148 strcpy(rproc
[s
].r_cmd
, "/sbin/");
149 strcpy(rproc
[s
].r_cmd
+6, ip
->proc_name
);
151 rproc
[s
].r_argv
[0] = rproc
[s
].r_cmd
;
152 rproc
[s
].r_argv
[1] = NULL
;
157 /* Set alarm to periodically check driver status. */
158 if (OK
!= (s
=sys_setalarm(RS_DELTA_T
, 0)))
159 panic("RS", "couldn't set alarm", s
);
161 /* See if we run in verbose mode. */
162 env_parse("rs_verbose", "d", 0, &rs_verbose
, 0, 1);
165 /*===========================================================================*
167 *===========================================================================*/
168 PRIVATE
void sig_handler()
173 /* Try to obtain signal set from PM. */
174 if (getsigset(&sigset
) != 0) return;
176 /* Check for known signals. */
177 if (sigismember(&sigset
, SIGCHLD
)) do_exit(NULL
);
178 if (sigismember(&sigset
, SIGTERM
)) do_shutdown(NULL
);
181 /*===========================================================================*
183 *===========================================================================*/
184 PRIVATE
void get_work(m_in
)
185 message
*m_in
; /* pointer to message */
187 int s
; /* receive status */
188 if (OK
!= (s
=receive(ANY
, m_in
))) /* wait for message */
189 panic("RS","receive failed", s
);
193 /*===========================================================================*
195 *===========================================================================*/
196 PRIVATE
void reply(who
, m_out
)
197 int who
; /* replyee */
198 message
*m_out
; /* reply message */
200 /*message m_out;*/ /* reply message */
201 int s
; /* send status */
203 /*m_out.m_type = result;*/ /* build reply message */
204 if (OK
!= (s
=send(who
, m_out
))) /* send the message */
205 panic("RS", "unable to send reply", s
);