serialize: add new helper deserialize_fd()
Currently, when we deserialize an fd we do a lot of manual work. Add a common helper that makes this more robust and uniform. Note that this sometimes changes behaviour slightly, but in ways that shouldn't really matter: if we fail to deserialize an fd correctly we'll unset (i.e. set to -EBADF) the fd in the deserialized data structure. Previously, we'd leave the old value in place. This should not change effective result (as in either case we'll be in a bad state afterwards, just once we mix old/invalidated state with new state, while now we'll reset the state explicitly to invalidated state on failure). In particular as deserialization starts from an empty structure generally, hence the old value should be unset anyway. Another slight change is that if we fail to deserialize some object half way, and we already have taken out one fd from the serialized fdset we'll now just close it instead of returning it to/leaving it in the fdset. Given that such "orphaned" fds are blanket closed after deserialization finishes this also shouldn't change behaviour IRL. Also, the idle_pipe was previously incorrectly serialized: we'd serialize invalidated fds, which would fail, but because parsing errors on this were ignored on the deserializatin noone noticed. This is fixed.
This commit is contained in:
+21
-10
@@ -285,6 +285,23 @@ int deserialize_read_line(FILE *f, char **ret) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int deserialize_fd(FDSet *fds, const char *value) {
|
||||
_cleanup_close_ int our_fd = -EBADF;
|
||||
int parsed_fd;
|
||||
|
||||
assert(value);
|
||||
|
||||
parsed_fd = parse_fd(value);
|
||||
if (parsed_fd < 0)
|
||||
return log_debug_errno(parsed_fd, "Failed to parse file descriptor serialization: %s", value);
|
||||
|
||||
our_fd = fdset_remove(fds, parsed_fd); /* Take possession of the fd */
|
||||
if (our_fd < 0)
|
||||
return log_debug_errno(our_fd, "Failed to acquire fd from serialization fds: %m");
|
||||
|
||||
return TAKE_FD(our_fd);
|
||||
}
|
||||
|
||||
int deserialize_strv(char ***l, const char *value) {
|
||||
ssize_t unescaped_len;
|
||||
char *unescaped;
|
||||
@@ -372,18 +389,12 @@ int deserialize_pidref(FDSet *fds, const char *value, PidRef *ret) {
|
||||
|
||||
e = startswith(value, "@");
|
||||
if (e) {
|
||||
_cleanup_close_ int our_fd = -EBADF;
|
||||
int parsed_fd;
|
||||
int fd = deserialize_fd(fds, e);
|
||||
|
||||
parsed_fd = parse_fd(e);
|
||||
if (parsed_fd < 0)
|
||||
return log_debug_errno(parsed_fd, "Failed to parse file descriptor specification: %s", e);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
our_fd = fdset_remove(fds, parsed_fd); /* Take possession of the fd */
|
||||
if (our_fd < 0)
|
||||
return log_debug_errno(our_fd, "Failed to acquire pidfd from serialization fds: %m");
|
||||
|
||||
r = pidref_set_pidfd_consume(ret, TAKE_FD(our_fd));
|
||||
r = pidref_set_pidfd_consume(ret, fd);
|
||||
} else {
|
||||
pid_t pid;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user