Remove rc_service_wait as runscript.c should do the waiting. rc_deptree_depend now returns the exact depends as listed. This is so we can support a new 'keywords' directive. We can add whatever here, like 'notimeout' which means that an init script doesn't timeout. This removes the hardcoded check on checkfs and checkroot.

This commit is contained in:
Roy Marples 2007-12-05 17:48:07 +00:00
parent f40f7528be
commit 0490a9290a
11 changed files with 115 additions and 73 deletions

View File

@ -29,6 +29,7 @@ depend() {
need localmount
before logger
after clock sysctl
keywords notimeout
}
cleanup_tmp_dir() {

View File

@ -30,6 +30,7 @@ optionally repair them."
depend() {
need checkroot
after modules
keywords notimeout
}
do_checkfs() {

View File

@ -27,6 +27,10 @@
description="Check the root filesystem according to /etc/fstab for errors \
and optionally repair them."
depend() {
keywords notimeout
}
do_mtab() {
# Don't create mtab if /etc is readonly
if ! printf "" 2>/dev/null >/etc/mtab; then

View File

@ -29,6 +29,7 @@ and /etc/conf.d/local.stop when stopping."
depend() {
after *
keywords notimeout
}
start() {

View File

@ -45,7 +45,10 @@ after() {
}
provide() {
[ -n "$*" ] && echo "${SVCNAME} iprovide $*" >&3
}
}
keywords() {
[ -n "$*" ] && echo "${SVCNAME} keywords $*" >&3
}
depend() {
:
}
@ -83,6 +86,7 @@ for SVCNAME in *; do
before ${rc_before} ${RC_BEFORE}
after ${rc_after} ${RC_AFTER}
provide ${rc_provide} ${RC_PROVIDE}
keywords ${rc_keywords} ${RC_KEYWORDS}
fi
)
done

View File

@ -467,10 +467,34 @@ static void visit_service (rc_depinfo_t *deptree, const char * const *types,
rc_strlist_add (&sorted->list, depinfo->service);
}
char **rc_deptree_depend (rc_depinfo_t *deptree,
const char *service, const char *type)
{
rc_depinfo_t *di;
rc_deptype_t *dt;
char **svcs = NULL;
int i;
char *svc;
if (! (di = get_depinfo (deptree, service)) ||
! (dt = get_deptype (di, type)))
{
errno = ENOENT;
return (NULL);
}
/* For consistency, we copy the array */
STRLIST_FOREACH (dt->services, svc, i)
rc_strlist_add (&svcs, svc);
return (svcs);
}
librc_hidden_def(rc_deptree_depend)
char **rc_deptree_depends (rc_depinfo_t *deptree,
const char **types, const char **services,
const char *runlevel, int options)
{
{
struct lhead sorted;
struct lhead visited;
rc_depinfo_t *di;

View File

@ -35,14 +35,6 @@ const char copyright[] = "Copyright (c) 2007 Gentoo Foundation\n"
#include "librc.h"
/* usecs to wait while we poll the fifo */
#define WAIT_INTERVAL 20000000
/* max secs to wait until a service comes up */
#define WAIT_MAX 300
#define ONE_SECOND 1000000000
#define SOFTLEVEL RC_SVCDIR "/softlevel"
#ifndef S_IXUGO
@ -719,52 +711,6 @@ bool rc_service_schedule_clear (const char *service)
}
librc_hidden_def(rc_service_schedule_clear)
bool rc_service_wait (const char *service)
{
char *svc;
char *base;
char *fifo;
struct timespec ts;
int nloops = WAIT_MAX * (ONE_SECOND / WAIT_INTERVAL);
bool retval = false;
bool forever = false;
if (! service)
return (false);
svc = xstrdup (service);
base = basename (svc);
fifo = rc_strcatpaths (RC_SVCDIR, "exclusive", base, (char *) NULL);
/* FIXME: find a better way of doing this
* Maybe a setting in the init script? */
if (strcmp (base, "checkfs") == 0 || strcmp (base, "checkroot") == 0)
forever = true;
free (svc);
ts.tv_sec = 0;
ts.tv_nsec = WAIT_INTERVAL;
while (nloops) {
if (! exists (fifo)) {
retval = true;
break;
}
if (nanosleep (&ts, NULL) == -1) {
if (errno != EINTR)
break;
}
if (! forever)
nloops --;
}
if (! exists (fifo))
retval = true;
free (fifo);
return (retval);
}
librc_hidden_def(rc_service_wait)
char **rc_services_in_runlevel (const char *runlevel)
{

View File

@ -76,6 +76,7 @@
librc_hidden_proto(rc_config_list)
librc_hidden_proto(rc_config_load)
librc_hidden_proto(rc_config_value)
librc_hidden_proto(rc_deptree_depend)
librc_hidden_proto(rc_deptree_depends)
librc_hidden_proto(rc_deptree_free)
librc_hidden_proto(rc_deptree_load)
@ -104,7 +105,6 @@ librc_hidden_proto(rc_service_schedule_clear)
librc_hidden_proto(rc_service_schedule_start)
librc_hidden_proto(rc_service_start)
librc_hidden_proto(rc_service_stop)
librc_hidden_proto(rc_service_wait)
librc_hidden_proto(rc_services_in_runlevel)
librc_hidden_proto(rc_services_in_state)
librc_hidden_proto(rc_services_scheduled)

View File

@ -211,11 +211,6 @@ char *rc_service_value_get (const char *service, const char *option);
bool rc_service_value_set (const char *service, const char *option,
const char *value);
/*! Wait for a service to finish
* @param service to wait for
* @return true if service finished before timeout, otherwise false */
bool rc_service_wait (const char *service);
/*! List the services in a runlevel
* @param runlevel to list
* @return NULL terminated list of services */
@ -275,6 +270,14 @@ bool rc_deptree_update_needed (void);
* @return pointer to the dependency tree */
rc_depinfo_t *rc_deptree_load (void);
/*! List the depend for the type of service
* @param deptree to search
* @param type to use (keywords, etc)
* @param service to check
* @return NULL terminated list of services in order */
char **rc_deptree_depend (rc_depinfo_t *deptree,
const char *type, const char *service);
/*! List all the services in order that the given services have
* for the given types and options.
* @param deptree to search

View File

@ -3,6 +3,7 @@ global:
rc_config_list;
rc_config_load;
rc_config_value;
rc_deptree_depend;
rc_deptree_depends;
rc_deptree_free;
rc_deptree_load;
@ -32,7 +33,6 @@ global:
rc_service_schedule_start;
rc_service_start;
rc_service_stop;
rc_service_wait;
rc_services_in_runlevel;
rc_services_in_state;
rc_services_scheduled;

View File

@ -68,6 +68,14 @@
#define PREFIX_LOCK RC_SVCDIR "/prefix.lock"
/* usecs to wait while we poll the fifo */
#define WAIT_INTERVAL 20000000
/* max secs to wait until a service comes up */
#define WAIT_MAX 300
#define ONE_SECOND 1000000000
static char *applet = NULL;
static char *service = NULL;
static char *exclusive = NULL;
@ -98,7 +106,6 @@ static const char *types_b[] = { "broken", NULL };
static const char *types_n[] = { "ineed", NULL };
static const char *types_nu[] = { "ineed", "iuse", NULL };
static const char *types_nua[] = { "ineed", "iuse", "iafter", NULL };
static const char *types_p[] = { "iprovide", NULL };
static const char *types_m[] = { "needsme", NULL };
static const char *types_mua[] = { "needsme", "usesme", "beforeme", NULL };
@ -492,6 +499,60 @@ static bool svc_exec (const char *arg1, const char *arg2)
return (execok);
}
static bool svc_wait (rc_depinfo_t *depinfo, const char *svc)
{
char *s;
char *base;
char *fifo;
struct timespec ts;
int nloops = WAIT_MAX * (ONE_SECOND / WAIT_INTERVAL);
bool retval = false;
bool forever = false;
char **keywords = NULL;
int i;
if (! service)
return (false);
/* Some services don't have a timeout, like checkroot and checkfs */
keywords = rc_deptree_depend (deptree, svc, "keywords");
STRLIST_FOREACH (keywords, s, i) {
if (strcmp (s, "notimeout") == 0) {
forever = true;
break;
}
}
rc_strlist_free (keywords);
s = xstrdup (svc);
base = basename (s);
fifo = rc_strcatpaths (RC_SVCDIR, "exclusive", base, (char *) NULL);
free (s);
ts.tv_sec = 0;
ts.tv_nsec = WAIT_INTERVAL;
while (nloops) {
if (! exists (fifo)) {
retval = true;
break;
}
if (nanosleep (&ts, NULL) == -1) {
if (errno != EINTR)
break;
}
if (! forever)
nloops --;
}
if (! exists (fifo))
retval = true;
free (fifo);
return (retval);
}
static rc_service_state_t svc_status ()
{
char status[10];
@ -683,7 +744,7 @@ static void svc_start (bool deps)
continue;
}
if (! rc_service_wait (svc))
if (! svc_wait (deptree, svc))
eerror ("%s: timed out waiting for %s", applet, svc);
if ((svcs = rc_service_state (svc)) & RC_SERVICE_STARTED)
continue;
@ -710,12 +771,9 @@ static void svc_start (bool deps)
unlink_mtime_test ();
STRLIST_FOREACH (tmplist, svc, i) {
const char *sl[] = { svc, NULL };
rc_service_schedule_start (svc, service);
rc_strlist_free (providelist);
providelist = rc_deptree_depends (deptree, types_p, sl,
softlevel, depoptions);
providelist = rc_deptree_depend (deptree, "iprovide", svc);
STRLIST_FOREACH (providelist, svc2, j)
rc_service_schedule_start (svc2, service);
@ -780,7 +838,7 @@ static void svc_start (bool deps)
/* Do the same for any services we provide */
rc_strlist_free (tmplist);
tmplist = rc_deptree_depends (deptree, types_p, svcl, softlevel, depoptions);
tmplist = rc_deptree_depend (deptree, "iprovide", applet);
STRLIST_FOREACH (tmplist, svc2, j) {
rc_strlist_free (services);
@ -853,7 +911,7 @@ static void svc_stop (bool deps)
if (svcs & RC_SERVICE_STARTED ||
svcs & RC_SERVICE_INACTIVE)
{
rc_service_wait (svc);
svc_wait (deptree, svc);
svcs = rc_service_state (svc);
if (svcs & RC_SERVICE_STARTED ||
svcs & RC_SERVICE_INACTIVE)
@ -873,7 +931,7 @@ static void svc_stop (bool deps)
continue;
/* We used to loop 3 times here - maybe re-do this if needed */
rc_service_wait (svc);
svc_wait (deptree, svc);
if (! (rc_service_state (svc) & RC_SERVICE_STOPPED)) {
if (rc_runlevel_stopping ()) {
/* If shutting down, we should stop even if a dependant failed */
@ -899,7 +957,7 @@ static void svc_stop (bool deps)
STRLIST_FOREACH (services, svc, i) {
if (rc_service_state (svc) & RC_SERVICE_STOPPED)
continue;
rc_service_wait (svc);
svc_wait (deptree, svc);
}
rc_strlist_free (services);