summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2017-07-31 02:05:35 -0400
committerMartin Pitt <martinpitt@users.noreply.github.com>2017-07-31 08:05:35 +0200
commit0742986650b36b604613f9aaa1f6bd45b51c0e67 (patch)
tree780ca1f54b04793074efe8814dab2ce40d4eec9f
parent01a45898fce8def67d51332bccc410eb1e8710e7 (diff)
downloadsystemd-0742986650b36b604613f9aaa1f6bd45b51c0e67.tar.gz
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.
-rw-r--r--src/core/manager.c33
-rw-r--r--src/core/unit.c21
-rw-r--r--src/core/unit.h1
3 files changed, 47 insertions, 8 deletions
diff --git a/src/core/manager.c b/src/core/manager.c
index d29acf500f..1aadb7076e 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -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;
diff --git a/src/core/unit.c b/src/core/unit.c
index 394832e8ba..a42c667754 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -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;
diff --git a/src/core/unit.h b/src/core/unit.h
index 5ecaba11e9..a384f264ee 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -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);