Permalink
Browse files

Fixed hang on rc_parallel=yes

  • Loading branch information...
1 parent de18640 commit a0899e2fd03cb78ac6c8b084cc6fa80b7c3eca8f @xaionaro committed Jan 19, 2014
Showing with 45 additions and 9 deletions.
  1. +19 −3 src/librc/librc-depend.c
  2. +6 −4 src/librc/rc.h.in
  3. +20 −2 src/rc/runscript.c
@@ -376,6 +376,9 @@ visit_service(const RC_DEPTREE *deptree,
RC_STRINGLIST *provided;
RC_STRING *p;
const char *svcname;
+ svcname = getenv("RC_SVCNAME");
+
+ errno = 0; // 0 - succes; ELOOP - on dependencies loop
/* Check if we have already visited this service or not */
TAILQ_FOREACH(type, visited, entries)
@@ -390,6 +393,15 @@ visit_service(const RC_DEPTREE *deptree,
continue;
TAILQ_FOREACH(service, dt->services, entries) {
+ if(options&RC_DEP_CHECKLOOP)
+ /* Check for dependencies loop.
+ See: https://bugs.gentoo.org/show_bug.cgi?id=391945
+ */
+ if(!strcmp(svcname, service->value)) {
+ errno = ELOOP;
+ return;
+ }
+
if (!(options & RC_DEP_TRACE) ||
strcmp(type->value, "iprovide") == 0)
{
@@ -437,7 +449,6 @@ visit_service(const RC_DEPTREE *deptree,
/* We've visited everything we need, so add ourselves unless we
are also the service calling us or we are provided by something */
- svcname = getenv("RC_SVCNAME");
if (!svcname || strcmp(svcname, depinfo->service) != 0) {
if (!get_deptype(depinfo, "providedby"))
rc_stringlist_add(sorted, depinfo->service);
@@ -478,6 +489,7 @@ rc_deptree_depends(const RC_DEPTREE *deptree,
RC_STRINGLIST *visited = rc_stringlist_new();
RC_DEPINFO *di;
const RC_STRING *service;
+ errno = 0; // 0 - on success; ELOOP - on dependencies loop
bootlevel = getenv("RC_BOOTLEVEL");
if (!bootlevel)
@@ -488,8 +500,12 @@ rc_deptree_depends(const RC_DEPTREE *deptree,
continue;
}
if (types)
- visit_service(deptree, types, sorted, visited,
- di, runlevel, options);
+ if(visit_service(deptree, types, sorted, visited,
+ di, runlevel, options), errno) {
+ rc_stringlist_free(sorted);
+ rc_stringlist_free(visited);
+ return NULL;
+ }
}
rc_stringlist_free(visited);
return sorted;
View
@@ -305,13 +305,15 @@ const char *rc_sys_v2(void);
* These options can change the services found by the rc_get_depinfo and
* rc_get_depends functions. */
/*! Trace provided services */
-#define RC_DEP_TRACE (1<<0)
+#define RC_DEP_TRACE (1<<0)
/*! Only use services added to runlevels */
-#define RC_DEP_STRICT (1<<1)
+#define RC_DEP_STRICT (1<<1)
/*! Runlevel is starting */
-#define RC_DEP_START (1<<2)
+#define RC_DEP_START (1<<2)
/*! Runlevel is stopping */
-#define RC_DEP_STOP (1<<3)
+#define RC_DEP_STOP (1<<3)
+/*! Check for dependencies loop */
+#define RC_DEP_CHECKLOOP (1<<4)
/*! @name Dependencies
* We analyse each init script and cache the resultant dependency tree.
View
@@ -690,9 +690,27 @@ svc_start_deps(void)
if (dry_run)
return;
- /* Now wait for them to start */
+ /* Getting dependencies to start */
services = rc_deptree_depends(deptree, types_nua, applet_list,
- runlevel, depoptions);
+ runlevel,
+ depoptions|(rc_conf_yesno("rc_parallel")?RC_DEP_CHECKLOOP:0));
+
+ if(services == NULL) {
+ switch(errno) {
+ case ELOOP:
+ eerrorx("ERROR: %s failed to start. Dependencies loop.", applet);
+ break;
+ default:
+ eerrorx("ERROR: %s failed to start. Unknown error.", applet);
+ break;
+ }
+ rc_stringlist_free(services);
+ services = NULL;
+ return;
+ }
+
+ /* Now wait for them to start */
+
/* We use tmplist to hold our scheduled by list */
tmplist = rc_stringlist_new();
TAILQ_FOREACH(svc, services, entries) {

0 comments on commit a0899e2

Please sign in to comment.