Refactor end of bootstrap using new work queue helper

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
Joachim Nilsson
2018-10-09 07:14:33 +02:00
parent 4870cab898
commit df22628183
3 changed files with 65 additions and 53 deletions
+60 -23
View File
@@ -47,6 +47,7 @@
#include "tty.h"
#include "util.h"
#include "utmp-api.h"
#include "schedule.h"
int runlevel = 0; /* Bootstrap 'S' */
int cfglevel = RUNLEVEL; /* Fallback if no configured runlevel */
@@ -63,6 +64,9 @@ char *runparts = NULL;
uev_ctx_t *ctx = NULL; /* Main loop context */
svc_t *wdog = NULL; /* No watchdog by default */
static int udev = 0; /* Runtime detection of udev */
/*
* Show user configured banner before service bootstrap progress
*/
@@ -261,13 +265,61 @@ static void finalize(void)
tty_runlevel();
}
/*
* Start cranking the big state machine
*/
static void crank_worker(void *unused)
{
/*
* Initalize state machine and start all bootstrap tasks
* NOTE: no network available!
*/
sm_init(&sm);
sm_step(&sm);
/* Debian has this little script to copy generated rules while the system was read-only */
if (udev && fexist("/lib/udev/udev-finish"))
run_interactive("/lib/udev/udev-finish", "Finalizing udev");
}
/*
* Wait for system bootstrap to complete, all SVC_TYPE_RUNTASK must be
* allowed to complete their work in [S], or timeout, before we call
* finalize(), should not take more than 120 sec.
*/
static void final_worker(void *work)
{
static int cnt = 120;
_d("Step all services ...");
service_step_all(SVC_TYPE_ANY);
if (cnt-- > 0 && !service_completed()) {
_d("Not all bootstrap run/tasks have completed yet ... %d", cnt);
schedule_work(work);
return;
}
if (cnt > 0)
_d("All run/task have completed, resuming bootstrap.");
else
_d("Timeout, resuming bootstrap.");
finalize();
}
int main(int argc, char* argv[])
{
struct wq crank = {
.cb = crank_worker
};
struct wq final = {
.cb = final_worker,
.delay = 1000
};
uev_ctx_t loop;
char *path;
char cmd[256];
int udev = 0;
uev_t timer; /* Bootstrap timer, on timeout call finalize() */
uev_ctx_t loop;
/*
* finit/init/telinit client tool uses /dev/initctl pipe
@@ -466,33 +518,18 @@ int main(int argc, char* argv[])
*/
conf_monitor(&loop);
/*
* Initalize state machine and start all bootstrap tasks
* NOTE: no network available!
*/
sm_init(&sm);
sm_step(&sm);
/* Debian has this little script to copy generated rules while the system was read-only */
if (udev && fexist("/lib/udev/udev-finish"))
run_interactive("/lib/udev/udev-finish", "Finalizing udev");
/* Start new initctl API responder */
_d("Starting initctl API responder ...");
api_init(&loop);
umask(022);
/* Finalize bootstrap, allow service/run/tasks to complete */
service_step_all(SVC_TYPE_ANY);
_d("Starting the big state machine ...");
schedule_work(&crank);
/*
* Wait for all SVC_TYPE_RUNTASK to have completed their work in
* [S], or timeout, before calling finalize()
*/
_d("Starting bootstrap finalize timer ...");
uev_timer_init(&loop, &timer, service_bootstrap_cb, finalize, 1000, 1000);
schedule_work(&final);
/*
* Enter main loop to monior /dev/initctl and services
* Enter main loop to monitor /dev/initctl and services
*/
_d("Entering main loop ...");
return uev_run(&loop, 0);
+4 -29
View File
@@ -1243,21 +1243,20 @@ void service_runtask_clean(void)
}
/**
* service_runtask_completed - Have run/task completed in current runlevel
* @skip: Hardcoded list of conditions to skip
* service_completed - Have run/task completed in current runlevel
*
* This function checks if all run/task have run once in the current
* runlevel. E.g., at bootstrap we must wait for these scripts or
* programs to complete their run before switching to the configured
* runlevel.
*
* Setting @skip means skipping tasks with %HOOK_SVC_UP, %HOOK_SYSTEM_UP
* set in their condition mask. These tasks cannot run until finalize()
* All tasks with %HOOK_SVC_UP, %HOOK_SYSTEM_UP set in their condition
* mask are skipped. These tasks cannot run until finalize()
*
* Returns:
* %TRUE(1) or %FALSE(0)
*/
int service_runtask_completed(int skip)
int service_completed(void)
{
svc_t *svc, *iter = NULL;
@@ -1284,30 +1283,6 @@ int service_runtask_completed(int skip)
return 1;
}
/*
* Wait for system bootstrap to complete, should not take more than 120 sec.
*/
void service_bootstrap_cb(uev_t *w, void *arg, int events)
{
static int cnt = 120;
void (*finalize)(void) = arg;
_d("Step all services ...");
service_step_all(SVC_TYPE_ANY);
_d("Checking completion of all run/task ... %d", cnt);
if (cnt-- > 0 && !service_runtask_completed(!runlevel))
return;
if (cnt > 0)
_d("All run/task have completed, resuming bootstrap.");
else
_d("Timeout, resuming bootstrap.");
cnt = 10;
uev_timer_stop(w);
finalize();
}
/**
* Local Variables:
* indent-tabs-mode: t
+1 -1
View File
@@ -38,7 +38,7 @@ int service_step (svc_t *svc);
void service_step_all (int types);
void service_worker (void *unused);
void service_bootstrap_cb (uev_t *w, void *arg, int events);
int service_completed (void);
#endif /* FINIT_SERVICE_H_ */