summaryrefslogtreecommitdiff
path: root/src/shared/eventfd-util.h
diff options
context:
space:
mode:
authorDjalal Harouni <tixxdz@opendz.org>2014-05-24 14:58:55 +0100
committerLennart Poettering <lennart@poettering.net>2014-05-25 11:23:35 +0800
commite866af3acc30fcd1183a028ea3ef552b7237cc55 (patch)
treed13ad460ed1206420bb7e3e7dcbda67b30c052b9 /src/shared/eventfd-util.h
parent113cea802db444beab4783538d39966f707be788 (diff)
nspawn: make nspawn robust to container failure
nspawn and the container child use eventfd to wait and notify each other that they are ready so the container setup can be completed. However in its current form the wait/notify event ignore errors that may especially affect the child (container). On errors the child will jump to the "child_fail" label and terminate with _exit(EXIT_FAILURE) without notifying the parent. Since the eventfd is created without the "EFD_NONBLOCK" flag, this leaves the parent blocking on the eventfd_read() call. The container can also be killed at any moment before execv() and the parent will not receive notifications. We can fix this by using cheap mechanisms, the new high level eventfd API and handle SIGCHLD signals: * Keep the cheap eventfd and EFD_NONBLOCK flag. * Introduce eventfd states for parent and child to sync. Child notifies parent with EVENTFD_CHILD_SUCCEEDED on success or EVENTFD_CHILD_FAILED on failure and before _exit(). This prevents the parent from waiting on an event that will never come. * If the child is killed before execv() or before notifying the parent, we install a NOP handler for SIGCHLD which will interrupt blocking calls with EINTR. This gives a chance to the parent to call wait() and terminate in main(). * If there are no errors, parent will block SIGCHLD, restore default handler and notify child which will do execv(), then parent will pass control to process_pty() to do its magic. This was exposed in part by: https://bugs.freedesktop.org/show_bug.cgi?id=76193 Reported-by: Tobias Hunger tobias.hunger@gmail.com
Diffstat (limited to 'src/shared/eventfd-util.h')
-rw-r--r--src/shared/eventfd-util.h43
1 files changed, 43 insertions, 0 deletions
diff --git a/src/shared/eventfd-util.h b/src/shared/eventfd-util.h
new file mode 100644
index 0000000000..0120f0409e
--- /dev/null
+++ b/src/shared/eventfd-util.h
@@ -0,0 +1,43 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2014 Djalal Harouni
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <sys/types.h>
+#include <sys/eventfd.h>
+
+enum {
+ EVENTFD_INIT,
+ EVENTFD_START,
+ EVENTFD_PARENT_SUCCEEDED,
+ EVENTFD_PARENT_FAILED,
+ EVENTFD_CHILD_SUCCEEDED,
+ EVENTFD_CHILD_FAILED,
+};
+
+pid_t clone_with_eventfd(int flags, int eventfds[2]);
+
+int eventfd_send_state(int efd, eventfd_t s);
+int eventfd_recv_state(int efd, eventfd_t *e, eventfd_t s);
+
+int eventfd_recv_start(int efd);
+int eventfd_parent_succeeded(int efd);
+int eventfd_child_succeeded(int efd);