diff options
Diffstat (limited to 'src/shared/eventfd-util.c')
-rw-r--r-- | src/shared/eventfd-util.c | 169 |
1 files changed, 0 insertions, 169 deletions
diff --git a/src/shared/eventfd-util.c b/src/shared/eventfd-util.c deleted file mode 100644 index 27b7cf788f..0000000000 --- a/src/shared/eventfd-util.c +++ /dev/null @@ -1,169 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - 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 <assert.h> -#include <errno.h> -#include <unistd.h> -#include <sys/eventfd.h> -#include <sys/syscall.h> - -#include "eventfd-util.h" -#include "util.h" - - -/* - * Use this to create processes that need to setup a full context - * and sync it with their parents using cheap mechanisms. - * - * This will create two blocking eventfd(s). A pair for the parent and - * the other for the child so they can be used as a notify mechanism. - * Each process will gets its copy of the parent and child eventfds. - * - * This is useful in case: - * 1) If the parent fails or dies, the child must die. - * 2) Child will install PR_SET_PDEATHSIG as soon as possible. - * 3) Parent and child need to sync using less resources. - * 4) If parent is not able to install a SIGCHLD handler: - * parent will wait using a blocking eventfd_read() or - * eventfd_child_succeeded() call on the child eventfd. - * - * * If the child setup succeeded, child should notify with an - * EVENTFD_CHILD_SUCCEEDED, parent will continue. - * * If the child setup failed, child should notify with an - * EVENTFD_CHILD_FAILED before any _exit(). This avoids blocking - * the parent. - * - * 5) If parent is able to install a SIGCHLD handler: - * An empty signal handler without SA_RESTART will do it, since the - * blocking eventfd_read() or eventfd_parent_succeeded() of the - * parent will be interrupted by SIGCHLD and the call will fail with - * EINTR. This is useful in case the child dies abnormaly and did - * not have a chance to notify its parent using EVENTFD_CHILD_FAILED. - * - * 6) Call wait*() in the main instead of the signal handler in order - * to: 1) reduce side effects and 2) have a better handling for - * child termination in order to reduce various race conditions. - * - * - * The return value of clone_with_eventfd() is the same of clone(). - * On success the eventfds[] will contain the two eventfd(s). These - * file descriptors can be closed later with safe_close(). On failure, - * a negative value is returned in the caller's context, and errno will - * be set appropriately. - * - * Extra preliminary work: - * 1) Child can wait before starting its setup by using the - * eventfd_recv_start() call on the parent eventfd, in that case the - * parent must notify with EVENTFD_START, after doing any preliminary - * work. - * - * Note: this function depends on systemd internal functions - * safe_close() and it should be used only by direct binaries, no - * libraries. - */ -pid_t clone_with_eventfd(int flags, int eventfds[2]) { - pid_t pid; - - assert(eventfds); - - eventfds[0] = eventfd(EVENTFD_INIT, EFD_CLOEXEC); - if (eventfds[0] < 0) - return -1; - - eventfds[1] = eventfd(EVENTFD_INIT, EFD_CLOEXEC); - if (eventfds[1] < 0) - goto err_eventfd0; - - pid = syscall(__NR_clone, flags, NULL); - if (pid < 0) - goto err_eventfd1; - - return pid; - -err_eventfd1: - eventfds[1] = safe_close(eventfds[1]); -err_eventfd0: - eventfds[0] = safe_close(eventfds[0]); - return -1; -} - -int eventfd_send_state(int efd, eventfd_t s) { - return eventfd_write(efd, s); -} - -/* - * Receive an eventfd state on the eventfd file descriptor. - * - * If the third argument is set to a value other than zero, then this - * function will compare the received value with this argument and set - * the return value. - * - * On success return 0. On error, -1 will be returned, and errno will - * be set appropriately. - */ -int eventfd_recv_state(int efd, eventfd_t *e, eventfd_t s) { - int ret; - - ret = eventfd_read(efd, e); - if (ret < 0) - return ret; - else if (s != 0 && *e != s) { - errno = EINVAL; - return -1; - } - - return 0; -} - -/* - * Receive the EVENTFD_START state on the eventfd file descriptor. - * - * On Success return 0. On error, -1 will be returned, and errno will - * be set appropriately. - */ -int eventfd_recv_start(int efd) { - eventfd_t e = EVENTFD_INIT; - return eventfd_recv_state(efd, &e, EVENTFD_START); -} - -/* - * Receive the EVENTFD_PARENT_SUCCEEDED state on the eventfd file - * descriptor. - * - * On Success return 0. On error, -1 will be returned, and errno will - * be set appropriately. - */ -int eventfd_parent_succeeded(int efd) { - eventfd_t e = EVENTFD_INIT; - return eventfd_recv_state(efd, &e, EVENTFD_PARENT_SUCCEEDED); -} - -/* - * Receive the EVENTFD_CHILD_SUCCEEDED state on the eventfd file - * descriptor. - * - * On Success return 0. On error, -1 will be returned, and errno will - * be set appropriately. - */ -int eventfd_child_succeeded(int efd) { - eventfd_t e = EVENTFD_INIT; - return eventfd_recv_state(efd, &e, EVENTFD_CHILD_SUCCEEDED); -} |