@@ -, +, @@ src/librc/librc-depend.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 59 insertions(+), 0 deletions(-) --- a/src/librc/librc-depend.c +++ a/src/librc/librc-depend.c @@ -442,6 +442,61 @@ visit_service(const RC_DEPTREE *deptree, } } +static void +remove_wrong_depends(RC_DEPTREE *deptree, const char *type) +{ + /* Remove wrong dependencies: + * svc1 > svc2 > svc3 > svc1 + * svc1 < svc2 < svc3 < svc1 + * '>' means 'ibefore', '<' means 'iafter'. + */ + + RC_DEPINFO *depinfo = NULL, *di, *di2; + RC_DEPTYPE *deptype = NULL, *dt, *dt2; + RC_STRING *s, *s_np, *s2, *s2_np, *s3, *s3_np; + char *svc1, *svc2, *svc3; + + TAILQ_FOREACH(depinfo, deptree, entries) { + if ((deptype = get_deptype(depinfo, type))) { + svc1 = depinfo->service; + TAILQ_FOREACH_SAFE(s, deptype->services, entries, s_np) { + svc2 = s->value; // svc2 != svc1 + if ((di = get_depinfo(deptree, svc2)) && + (dt = get_deptype(di, type))) { + TAILQ_FOREACH_SAFE(s2, dt->services, entries, s2_np) { + svc3 = s2->value; // svc3 != svc2 && svc3 != svc1 + if (strcmp(svc3, svc1) && + (di2 = get_depinfo(deptree, svc3)) && + (dt2 = get_deptype(di2, type))) { + TAILQ_FOREACH_SAFE(s3, dt2->services, entries, s3_np) { + if (!strcmp(s3->value, svc1)) { + /* svc1 > svc2 > svc3 > (s3->value) = svc1 */ + // printf("Wrong deps: %s %s %s\n", svc1, svc2, svc3); + + /* Remove svc3 > svc1, svc2 > svc3 and svc1 > svc2. */ + rc_stringlist_delete(dt2->services, svc1); + rc_stringlist_delete(dt->services, svc3); + rc_stringlist_delete(deptype->services, svc2); + } + } + } + } + } + } + } + } + + /* 1. svc1 > svc2 > svc1 doesn't hang, so we check svc3 != svc1. + * 2. Assume we have three wrong dependencies: + * crypto-loop > localmount > migrate-run + * hwclock > localmount > migrate-run + * localmount > migrate-run > modules + * Remove first one, second and third ones will not be wrong dependencies. + * 3. We could remove wrong dependencies ( svc1 > svc2 > svc3 > svc4 > svc1 ) + * in a similar way. + */ +} + RC_STRINGLIST * rc_deptree_depend(const RC_DEPTREE *deptree, const char *service, const char *type) @@ -998,6 +1053,10 @@ rc_deptree_update(void) } rc_stringlist_free(types); + /* Phase 5.5 - wrong dependencies cause a hang in parallel mode */ + remove_wrong_depends(deptree, "ibefore"); + remove_wrong_depends(deptree, "iafter"); + /* Phase 6 - save to disk Now that we're purely in C, do we need to keep a shell parseable file? I think yes as then it stays human readable