From 0490a9290a6af4a4923cc79fd380bc00a0a702e3 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Wed, 5 Dec 2007 17:48:07 +0000 Subject: [PATCH] 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. --- init.d/bootmisc | 1 + init.d/checkfs | 1 + init.d/checkroot | 4 +++ init.d/local | 1 + sh/gendepends.sh | 6 +++- src/librc-depend.c | 26 +++++++++++++++- src/librc.c | 54 -------------------------------- src/librc.h | 2 +- src/rc.h | 13 +++++--- src/rc.map | 2 +- src/runscript.c | 78 ++++++++++++++++++++++++++++++++++++++++------ 11 files changed, 115 insertions(+), 73 deletions(-) diff --git a/init.d/bootmisc b/init.d/bootmisc index 3ac53a22..f57a7086 100755 --- a/init.d/bootmisc +++ b/init.d/bootmisc @@ -29,6 +29,7 @@ depend() { need localmount before logger after clock sysctl + keywords notimeout } cleanup_tmp_dir() { diff --git a/init.d/checkfs b/init.d/checkfs index 4174b9b4..c29c519a 100755 --- a/init.d/checkfs +++ b/init.d/checkfs @@ -30,6 +30,7 @@ optionally repair them." depend() { need checkroot after modules + keywords notimeout } do_checkfs() { diff --git a/init.d/checkroot b/init.d/checkroot index 1397374a..acfb914a 100755 --- a/init.d/checkroot +++ b/init.d/checkroot @@ -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 diff --git a/init.d/local b/init.d/local index 461b4aff..d1c30d40 100755 --- a/init.d/local +++ b/init.d/local @@ -29,6 +29,7 @@ and /etc/conf.d/local.stop when stopping." depend() { after * + keywords notimeout } start() { diff --git a/sh/gendepends.sh b/sh/gendepends.sh index eac247dc..4fb2c8ed 100755 --- a/sh/gendepends.sh +++ b/sh/gendepends.sh @@ -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 diff --git a/src/librc-depend.c b/src/librc-depend.c index 5f0cacbb..ee6c79b7 100644 --- a/src/librc-depend.c +++ b/src/librc-depend.c @@ -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; diff --git a/src/librc.c b/src/librc.c index 0fdf6e09..e429318b 100644 --- a/src/librc.c +++ b/src/librc.c @@ -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) { diff --git a/src/librc.h b/src/librc.h index de035fd0..f3ebd596 100644 --- a/src/librc.h +++ b/src/librc.h @@ -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) diff --git a/src/rc.h b/src/rc.h index 8d5f32ea..6a53e7ce 100644 --- a/src/rc.h +++ b/src/rc.h @@ -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 diff --git a/src/rc.map b/src/rc.map index b487b663..e5f8ee34 100644 --- a/src/rc.map +++ b/src/rc.map @@ -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; diff --git a/src/runscript.c b/src/runscript.c index e58b1ed0..f81db232 100644 --- a/src/runscript.c +++ b/src/runscript.c @@ -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);