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
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
];
27 /*===========================================================================*
29 *===========================================================================*/
32 /* This is the main routine of this service. The main loop consists of
33 * three major activities: getting new work, processing the work, and
34 * sending the reply. The loop never terminates, unless a panic occurs.
36 message m
; /* request message */
37 int call_nr
, who_e
,who_p
; /* call number and caller */
38 int result
; /* result to return */
39 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.
85 if (call_nr
< RS_RQ_BASE
|| call_nr
>= RS_RQ_BASE
+0x100)
87 /* Ignore invalid requests. Do not try to reply. */
88 printf("RS: got invalid request %d from endpoint %d\n",
93 /* Only root can make calls to rs */
94 euid
= getpeuid(m
.m_source
);
97 printf("RS: got unauthorized request %d from endpoint %d\n",
105 case RS_UP
: result
= do_up(&m
, FALSE
, 0); break;
106 case RS_UP_COPY
: result
= do_up(&m
, TRUE
, 0); break;
107 case RS_START
: result
= do_start(&m
); break;
108 case RS_DOWN
: result
= do_down(&m
); break;
109 case RS_REFRESH
: result
= do_refresh(&m
); break;
110 case RS_RESTART
: result
= do_restart(&m
); break;
111 case RS_SHUTDOWN
: result
= do_shutdown(&m
); break;
112 case GETSYSINFO
: result
= do_getsysinfo(&m
); break;
114 printf("Warning, RS got unexpected request %d from %d\n",
115 m
.m_type
, m
.m_source
);
119 /* Finally send reply message, unless disabled. */
120 if (result
!= EDONTREPLY
) {
129 /*===========================================================================*
131 *===========================================================================*/
132 PRIVATE
void init_server(void)
134 /* Initialize the reincarnation server. */
136 struct boot_image
*ip
;
139 /* Install signal handlers. Ask PM to transform signal into message. */
140 sa
.sa_handler
= SIG_MESS
;
141 sigemptyset(&sa
.sa_mask
);
143 if (sigaction(SIGCHLD
,&sa
,NULL
)<0) panic("RS","sigaction failed", errno
);
144 if (sigaction(SIGTERM
,&sa
,NULL
)<0) panic("RS","sigaction failed", errno
);
146 /* Initialize the system process table. Use the boot image from the kernel
147 * and the device map from the FS to gather all needed information.
149 if ((s
= sys_getimage(image
)) != OK
)
150 panic("RS","warning: couldn't get copy of image table", s
);
152 /* Set alarm to periodically check driver status. */
153 if (OK
!= (s
=sys_setalarm(RS_DELTA_T
, 0)))
154 panic("RS", "couldn't set alarm", s
);
156 /* See if we run in verbose mode. */
157 env_parse("rs_verbose", "d", 0, &rs_verbose
, 0, 1);
159 /* Initialize the exec pipe. */
160 if (pipe(exec_pipe
) == -1)
161 panic("RS", "pipe failed", errno
);
162 if (fcntl(exec_pipe
[0], F_SETFD
,
163 fcntl(exec_pipe
[0], F_GETFD
) | FD_CLOEXEC
) == -1)
165 panic("RS", "fcntl set FD_CLOEXEC on pipe input failed", errno
);
167 if (fcntl(exec_pipe
[1], F_SETFD
,
168 fcntl(exec_pipe
[1], F_GETFD
) | FD_CLOEXEC
) == -1)
170 panic("RS", "fcntl set FD_CLOEXEC on pipe output failed", errno
);
172 if (fcntl(exec_pipe
[0], F_SETFL
,
173 fcntl(exec_pipe
[0], F_GETFL
) | O_NONBLOCK
) == -1)
175 panic("RS", "fcntl set O_NONBLOCK on pipe input failed", errno
);
179 /*===========================================================================*
181 *===========================================================================*/
182 PRIVATE
void sig_handler()
187 /* Try to obtain signal set from PM. */
188 if (getsigset(&sigset
) != 0) return;
190 /* Check for known signals. */
191 if (sigismember(&sigset
, SIGCHLD
)) do_exit(NULL
);
192 if (sigismember(&sigset
, SIGTERM
)) do_shutdown(NULL
);
195 /*===========================================================================*
197 *===========================================================================*/
198 PRIVATE
void get_work(m_in
)
199 message
*m_in
; /* pointer to message */
201 int s
; /* receive status */
202 if (OK
!= (s
=receive(ANY
, m_in
))) /* wait for message */
203 panic("RS","receive failed", s
);
207 /*===========================================================================*
209 *===========================================================================*/
210 PRIVATE
void reply(who
, m_out
)
211 int who
; /* replyee */
212 message
*m_out
; /* reply message */
214 int s
; /* send status */
216 s
= sendnb(who
, m_out
); /* send the message */
218 printf("RS: unable to send reply to %d: %d\n", who
, s
);