service: sysv priorities in link names should take precedence, since they are possibly fixed up by chkconfig

This commit is contained in:
Lennart Poettering 2010-04-24 04:26:33 +02:00
parent ab8cabad26
commit db06e3b6a5
3 changed files with 47 additions and 78 deletions

View File

@ -1536,15 +1536,15 @@ unsigned manager_dispatch_load_queue(Manager *m) {
return n;
}
int manager_load_unit(Manager *m, const char *name, const char *path, Unit **_ret) {
int manager_load_unit_prepare(Manager *m, const char *name, const char *path, Unit **_ret) {
Unit *ret;
int r;
assert(m);
assert(name || path);
/* This will load the service information files, but not actually
* start any services or anything. */
/* This will prepare the unit for loading, but not actually
* load anything from disk. */
if (path && !is_path(path))
return -EINVAL;
@ -1577,6 +1577,24 @@ int manager_load_unit(Manager *m, const char *name, const char *path, Unit **_re
unit_add_to_load_queue(ret);
unit_add_to_dbus_queue(ret);
if (_ret)
*_ret = ret;
return 0;
}
int manager_load_unit(Manager *m, const char *name, const char *path, Unit **_ret) {
Unit *ret;
int r;
assert(m);
/* This will load the service information files, but not actually
* start any services or anything. */
if ((r = manager_load_unit_prepare(m, name, path, &ret)) < 0)
return r;
manager_dispatch_load_queue(m);
if (_ret)
@ -1767,6 +1785,8 @@ static int manager_process_signal_fd(Manager *m) {
case SIGTERM:
if (m->running_as == MANAGER_INIT)
/* This is for compatibility with the
* original sysvinit */
m->exit_code = MANAGER_REEXECUTE;
else
m->exit_code = MANAGER_EXIT;

View File

@ -240,6 +240,7 @@ Unit *manager_get_unit(Manager *m, const char *name);
int manager_get_unit_from_dbus_path(Manager *m, const char *s, Unit **_u);
int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j);
int manager_load_unit_prepare(Manager *m, const char *name, const char *path, Unit **_ret);
int manager_load_unit(Manager *m, const char *name, const char *path, Unit **_ret);
int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool force, Job **_ret);

View File

@ -273,71 +273,12 @@ static int sysv_exec_commands(Service *s) {
return 0;
}
static int priority_from_rcd(Service *s, const char *init_script) {
char **p;
unsigned i;
STRV_FOREACH(p, UNIT(s)->meta.manager->sysvrcnd_path)
for (i = 0; i < ELEMENTSOF(rcnd_table); i += 2) {
char *path;
DIR *d;
struct dirent *de;
if (asprintf(&path, "%s/%s", *p, rcnd_table[i]) < 0)
return -ENOMEM;
d = opendir(path);
free(path);
if (!d) {
if (errno != ENOENT)
log_warning("opendir() failed on %s: %s", path, strerror(errno));
continue;
}
while ((de = readdir(d))) {
int a, b;
if (ignore_file(de->d_name))
continue;
if (de->d_name[0] != 'S')
continue;
if (strlen(de->d_name) < 4)
continue;
if (!streq(de->d_name + 3, init_script))
continue;
/* Yay, we found it! Now decode the priority */
a = undecchar(de->d_name[1]);
b = undecchar(de->d_name[2]);
if (a < 0 || b < 0)
continue;
s->sysv_start_priority = a*10 + b;
log_debug("Determined priority %i from link farm for %s", s->sysv_start_priority, UNIT(s)->meta.id);
closedir(d);
return 0;
}
closedir(d);
}
return 0;
}
static int service_load_sysv_path(Service *s, const char *path) {
FILE *f;
Unit *u;
unsigned line = 0;
int r;
bool normal_service;
enum {
NORMAL,
DESCRIPTION,
@ -416,7 +357,7 @@ static int service_load_sysv_path(Service *s, const char *path) {
if (start_priority < 0 || start_priority > 99)
log_warning("[%s:%u] Start priority out of range. Ignoring.", path, line);
else
else if (s->sysv_start_priority < 0)
s->sysv_start_priority = start_priority;
char_array_0(runlevels);
@ -434,7 +375,6 @@ static int service_load_sysv_path(Service *s, const char *path) {
s->sysv_runlevels = d;
}
} else if (startswith(t, "description:")) {
size_t k = strlen(t);
@ -634,20 +574,15 @@ static int service_load_sysv_path(Service *s, const char *path) {
* a priority for *all* init scripts here, since they are
* needed as soon as at least one non-LSB script is used. */
if (s->sysv_start_priority < 0) {
log_debug("%s has no chkconfig header, trying to determine SysV priority from link farm.", u->meta.id);
if ((r = priority_from_rcd(s, file_name_from_path(path))) < 0)
goto finish;
if (s->sysv_start_priority < 0)
log_warning("%s has neither a chkconfig header nor a directory link, cannot order unit!", u->meta.id);
}
if (s->sysv_start_priority < 0)
log_warning("%s has neither a chkconfig header nor a directory link, cannot order unit!", u->meta.id);
if ((r = sysv_exec_commands(s)) < 0)
goto finish;
if (!s->sysv_runlevels || chars_intersect("12345", s->sysv_runlevels)) {
normal_service = !s->sysv_runlevels || chars_intersect("12345", s->sysv_runlevels);
if (normal_service) {
/* If there a runlevels configured for this service
* but none of the standard ones, then we assume this
* is some special kind of service (which might be
@ -664,8 +599,8 @@ static int service_load_sysv_path(Service *s, const char *path) {
s->kill_mode = KILL_PROCESS_GROUP;
/* Don't timeout special services during boot (like fsck) */
if (s->sysv_runlevels && !chars_intersect("12345", s->sysv_runlevels))
s->timeout_usec = -1;
if (s->sysv_runlevels && !normal_service)
s->timeout_usec = 0;
u->meta.load_state = UNIT_LOADED;
r = 0;
@ -2210,6 +2145,7 @@ static int service_enumerate(Manager *m) {
while ((de = readdir(d))) {
Unit *service;
int a, b;
if (ignore_file(de->d_name))
continue;
@ -2220,6 +2156,12 @@ static int service_enumerate(Manager *m) {
if (strlen(de->d_name) < 4)
continue;
a = undecchar(de->d_name[1]);
b = undecchar(de->d_name[2]);
if (a < 0 || b < 0)
continue;
free(fpath);
fpath = NULL;
if (asprintf(&fpath, "%s/%s/%s", *p, rcnd_table[i], de->d_name) < 0) {
@ -2242,9 +2184,15 @@ static int service_enumerate(Manager *m) {
goto finish;
}
if ((r = manager_load_unit(m, name, NULL, &service)) < 0)
if ((r = manager_load_unit_prepare(m, name, NULL, &service)) < 0)
goto finish;
if (de->d_name[0] == 'S')
SERVICE(service)->sysv_start_priority = a*10 + b;
manager_dispatch_load_queue(m);
service = unit_follow_merge(service);
if (de->d_name[0] == 'S') {
Unit *runlevel_target;