1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-21 02:50:18 +03:00

core: properly handle deserialization of unknown unit types (#6476)

We just abort startup, without printing any error. Make sure we always
print something, and when we cannot deserialize some unit, just ignore it and
continue.

Fixup for 4bc5d27b942afa83cc3d95debd2ad48d42ac07a8. Without this, we would hang
in daemon-reexec after upgrade.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2017-07-31 02:05:35 -04:00 committed by Martin Pitt
parent 01a45898fc
commit 0742986650
3 changed files with 47 additions and 8 deletions

View File

@ -1343,8 +1343,11 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
dual_timestamp_get(&m->units_load_finish_timestamp);
/* Second, deserialize if there is something to deserialize */
if (serialization)
if (serialization) {
r = manager_deserialize(m, serialization, fds);
if (r < 0)
log_error_errno(r, "Deserialization failed: %m");
}
/* Any fds left? Find some unit which wants them. This is
* useful to allow container managers to pass some file
@ -2779,6 +2782,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
for (;;) {
Unit *u;
char name[UNIT_NAME_MAX+2];
const char* unit_name;
/* Start marker */
if (!fgets(name, sizeof(name), f)) {
@ -2791,14 +2795,23 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
}
char_array_0(name);
unit_name = strstrip(name);
r = manager_load_unit(m, strstrip(name), NULL, NULL, &u);
if (r < 0)
goto finish;
r = manager_load_unit(m, unit_name, NULL, NULL, &u);
if (r < 0) {
log_notice_errno(r, "Failed to load unit \"%s\", skipping deserialization: %m", unit_name);
if (r == -ENOMEM)
goto finish;
unit_deserialize_skip(f);
continue;
}
r = unit_deserialize(u, f, fds);
if (r < 0)
goto finish;
if (r < 0) {
log_notice_errno(r, "Failed to deserialize unit \"%s\": %m", unit_name);
if (r == -ENOMEM)
goto finish;
}
}
finish:
@ -2871,8 +2884,12 @@ int manager_reload(Manager *m) {
/* Second, deserialize our stored data */
q = manager_deserialize(m, f, fds);
if (q < 0 && r >= 0)
r = q;
if (q < 0) {
log_error_errno(q, "Deserialization failed: %m");
if (r >= 0)
r = q;
}
fclose(f);
f = NULL;

View File

@ -3111,6 +3111,27 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
return 0;
}
void unit_deserialize_skip(FILE *f) {
assert(f);
/* Skip serialized data for this unit. We don't know what it is. */
for (;;) {
char line[LINE_MAX], *l;
if (!fgets(line, sizeof line, f))
return;
char_array_0(line);
l = strstrip(line);
/* End marker */
if (isempty(l))
return;
}
}
int unit_add_node_link(Unit *u, const char *what, bool wants, UnitDependency dep) {
Unit *device;
_cleanup_free_ char *e = NULL;

View File

@ -563,6 +563,7 @@ bool unit_can_serialize(Unit *u) _pure_;
int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs);
int unit_deserialize(Unit *u, FILE *f, FDSet *fds);
void unit_deserialize_skip(FILE *f);
int unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value);
int unit_serialize_item_escaped(Unit *u, FILE *f, const char *key, const char *value);