Beispiel #1
0
int process_command_line(command_line* cmd_line) {
	int child_pid = fork();
	if (child_pid == 0) {
		// use pipe's fd for piping
		if (cmd_line->piped) {
			dup3(cmd_line->pipe_filedes[0], FD_STDIN);
			dup3(cmd_line->target_command_line->pipe_filedes[1], FD_STDOUT);
		}

		usleep(DELAY_EXEC_IN_MICRO_SECOND);

		char **argv = build_argv(cmd_line);
		execvp(argv[0], argv);
		fprintf(stderr, "failed to execute command \'%s\': No such file or directory\n", argv[0]);
		exit(-1);
	}

	cmd_line->pid = child_pid;
	
	if (equal_str(cmd_line->action, "wait")) {
		pid_t pid;
		int status;
		while ((pid = waitpid(child_pid, &status, 0))) {
			if (pid == -1 && errno == EINTR) {
				continue;
			}

			break;
		}
	}

	return 0;
}
Beispiel #2
0
static uint32_t execute_addr2line(char* buffer, uint32_t buffer_size, const char* image, void* addr)
{
   ssize_t len;
   int pipefd[2];
   uint32_t output_len;

   (void) pipe(pipefd);

   pid_t pid = fork();

   if (pid == 0)
      {
      char buf[32];
      int fd_stderr = open("/tmp/addr2line.err", O_CREAT | O_WRONLY, 0666);

      (void) close(pipefd[0]);

#  ifndef HAVE_DUP3
      (void) dup2(pipefd[1], STDOUT_FILENO);
      (void) dup2(fd_stderr, STDERR_FILENO);
#  else
      (void) dup3(pipefd[1], STDOUT_FILENO, O_CLOEXEC);
      (void) dup3(fd_stderr, STDERR_FILENO, O_CLOEXEC);
#  endif

      // Invokes addr2line utility to determine the function name
      // and the line information from an address in the code segment

      (void) snprintf(buf, sizeof(buf), "%p", addr);

      (void) execlp("addr2line", "addr2line", buf, "-f", "-C", "-e", image, (char*)0);

      abort();
      }

   (void) close(pipefd[1]);

   output_len = 0;

loop:
   len = read(pipefd[0], buffer + output_len, buffer_size - output_len);

   if (len > 0)
      {
      output_len += len;

      goto loop;
      }

   buffer[output_len] = 0;

   (void) close(pipefd[0]);

   (void) waitpid(pid, 0, 0);

   return output_len;
}
Beispiel #3
0
static int spawn_getent(const char *database, const char *key, pid_t *rpid) {
        int pipe_fds[2];
        pid_t pid;

        assert(database);
        assert(key);
        assert(rpid);

        if (pipe2(pipe_fds, O_CLOEXEC) < 0)
                return log_error_errno(errno, "Failed to allocate pipe: %m");

        pid = fork();
        if (pid < 0)
                return log_error_errno(errno, "Failed to fork getent child: %m");
        else if (pid == 0) {
                int nullfd;
                char *empty_env = NULL;

                if (dup3(pipe_fds[1], STDOUT_FILENO, 0) < 0)
                        _exit(EXIT_FAILURE);

                if (pipe_fds[0] > 2)
                        safe_close(pipe_fds[0]);
                if (pipe_fds[1] > 2)
                        safe_close(pipe_fds[1]);

                nullfd = open("/dev/null", O_RDWR);
                if (nullfd < 0)
                        _exit(EXIT_FAILURE);

                if (dup3(nullfd, STDIN_FILENO, 0) < 0)
                        _exit(EXIT_FAILURE);

                if (dup3(nullfd, STDERR_FILENO, 0) < 0)
                        _exit(EXIT_FAILURE);

                if (nullfd > 2)
                        safe_close(nullfd);

                (void) reset_all_signal_handlers();
                (void) reset_signal_mask();
                close_all_fds(NULL, 0);

                execle("/usr/bin/getent", "getent", database, key, NULL, &empty_env);
                execle("/bin/getent", "getent", database, key, NULL, &empty_env);
                _exit(EXIT_FAILURE);
        }

        pipe_fds[1] = safe_close(pipe_fds[1]);

        *rpid = pid;

        return pipe_fds[0];
}
Beispiel #4
0
int main(int argc, char *argv[]) {
        int r, fd = -1, saved_stderr = -1;

        log_parse_environment();
        log_open();

        r = parse_argv(argc, argv);
        if (r <= 0)
                goto finish;

        fd = sd_journal_stream_fd(arg_identifier, arg_priority, arg_level_prefix);
        if (fd < 0) {
                log_error("Failed to create stream fd: %s", strerror(-fd));
                r = fd;
                goto finish;
        }

        saved_stderr = fcntl(STDERR_FILENO, F_DUPFD_CLOEXEC, 3);

        if (dup3(fd, STDOUT_FILENO, 0) < 0 ||
            dup3(fd, STDERR_FILENO, 0) < 0) {
                log_error("Failed to duplicate fd: %m");
                r = -errno;
                goto finish;
        }

        if (fd >= 3)
                close_nointr_nofail(fd);

        fd = -1;

        if (argc <= optind)
                execl("/bin/cat", "/bin/cat", NULL);
        else
                execvp(argv[optind], argv + optind);

        r = -errno;

        /* Let's try to restore a working stderr, so we can print the error message */
        if (saved_stderr >= 0)
                dup3(saved_stderr, STDERR_FILENO, 0);

        log_error("Failed to execute process: %s", strerror(-r));

finish:
        if (fd >= 0)
                close_nointr_nofail(fd);

        if (saved_stderr >= 0)
                close_nointr_nofail(saved_stderr);

        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
Beispiel #5
0
static int run(int argc, char *argv[]) {
        _cleanup_close_ int  fd = -1, saved_stderr = -1;
        int r;

        log_parse_environment();
        log_open();

        r = parse_argv(argc, argv);
        if (r <= 0)
                return r;

        fd = sd_journal_stream_fd(arg_identifier, arg_priority, arg_level_prefix);
        if (fd < 0)
                return log_error_errno(fd, "Failed to create stream fd: %m");

        saved_stderr = fcntl(STDERR_FILENO, F_DUPFD_CLOEXEC, 3);

        r = rearrange_stdio(STDIN_FILENO, fd, fd); /* Invalidates fd on succcess + error! */
        TAKE_FD(fd);
        if (r < 0)
                return log_error_errno(r, "Failed to rearrange stdout/stderr: %m");

        if (argc <= optind)
                (void) execl("/bin/cat", "/bin/cat", NULL);
        else
                (void) execvp(argv[optind], argv + optind);
        r = -errno;

        /* Let's try to restore a working stderr, so we can print the error message */
        if (saved_stderr >= 0)
                (void) dup3(saved_stderr, STDERR_FILENO, 0);

        return log_error_errno(r, "Failed to execute process: %m");
}
Beispiel #6
0
/*! Duplicate File Descriptor.
 * \return whatever \c dup2 or \c dup3 returns.
 * \todo Better to use \c freopen?
 */
inline int dupx(int oldfd, int newfd)
{
#ifdef _GNU_SOURCE
    int flags = 0;
    return dup3(oldfd, newfd, flags);
#else
    return dup2(oldfd, newfd);
#endif
}
Beispiel #7
0
ATF_TC_BODY(dup3_max, tc)
{
	struct rlimit res;

	(void)memset(&res, 0, sizeof(struct rlimit));
	(void)getrlimit(RLIMIT_NOFILE, &res);

	errno = 0;
	ATF_REQUIRE_ERRNO(EBADF, dup3(STDERR_FILENO,
		res.rlim_cur + 1, O_CLOEXEC) == -1);
}
Beispiel #8
0
int uv__dup2_cloexec(int oldfd, int newfd) {
  int r;
#if defined(__FreeBSD__) && __FreeBSD__ >= 10
  do
    r = dup3(oldfd, newfd, O_CLOEXEC);
  while (r == -1 && errno == EINTR);
  if (r == -1)
    return -errno;
  return r;
#elif defined(__FreeBSD__) && defined(F_DUP2FD_CLOEXEC)
  do
    r = fcntl(oldfd, F_DUP2FD_CLOEXEC, newfd);
  while (r == -1 && errno == EINTR);
  if (r != -1)
    return r;
  if (errno != EINVAL)
    return -errno;
  /* Fall through. */
#elif defined(__linux__)
  static int no_dup3;
  if (!no_dup3) {
    do
      r = uv__dup3(oldfd, newfd, UV__O_CLOEXEC);
    while (r == -1 && (errno == EINTR || errno == EBUSY));
    if (r != -1)
      return r;
    if (errno != ENOSYS)
      return -errno;
    /* Fall through. */
    no_dup3 = 1;
  }
#endif
  {
    int err;
    do
      r = dup2(oldfd, newfd);
#if defined(__linux__)
    while (r == -1 && (errno == EINTR || errno == EBUSY));
#else
    while (r == -1 && errno == EINTR);
#endif

    if (r == -1)
      return -errno;

    err = uv__cloexec(newfd, 1);
    if (err) {
      uv__close(newfd);
      return err;
    }

    return r;
  }
}
Beispiel #9
0
STATIC int
copyfd(int from, int to, int cloexec)
{
	int newfd;

	if (cloexec && to > 2)
		newfd = dup3(from, to, O_CLOEXEC);
	else
		newfd = dup2(from, to);

	return newfd;
}
Beispiel #10
0
int dup2(int oldFD, int newFD, bool closeOnExec)
{
    int flags = 0;
    if (closeOnExec) {
        flags |= O_CLOEXEC;
    }
    int fd = dup3(oldFD, newFD, flags);
    if (fd == -1) {
        THROW_EXCEPTION(UtilsException, "dup3() failed", errno);
    }
    return fd;
}
Beispiel #11
0
static void
check_mode(bool _dup, bool _dup2, bool _dup3)
{
	int mode[3] = { O_RDONLY, O_WRONLY, O_RDWR   };
	int perm[5] = { 0700, 0400, 0600, 0444, 0666 };
	struct stat st, st1;
	int fd, fd1, fd2;
	size_t i, j;

	/*
	 * Check that a duplicated descriptor
	 * retains the mode of the original file.
	 */
	for (i = 0; i < __arraycount(mode); i++) {

		for (j = 0; j < __arraycount(perm); j++) {

			fd1 = open(path, mode[i] | O_CREAT, perm[j]);
			fd2 = open("/etc/passwd", O_RDONLY);

			ATF_REQUIRE(fd1 >= 0);
			ATF_REQUIRE(fd2 >= 0);

			if (_dup != false)
				fd = dup(fd1);
			else if (_dup2 != false)
				fd = dup2(fd1, fd2);
			else if (_dup3 != false)
				fd = dup3(fd1, fd2, O_CLOEXEC);
			else {
				fd = -1;
			}

			ATF_REQUIRE(fd >= 0);

			(void)memset(&st, 0, sizeof(struct stat));
			(void)memset(&st1, 0, sizeof(struct stat));

			ATF_REQUIRE(fstat(fd, &st) == 0);
			ATF_REQUIRE(fstat(fd1, &st1) == 0);

			if (st.st_mode != st1.st_mode)
				atf_tc_fail("invalid mode");

			(void)close(fd);
			(void)close(fd1);
			(void)close(fd2);
			(void)unlink(path);
		}
	}
}
Beispiel #12
0
int main()
{
  dup(2);
  //staptest// dup (2) = NNNN
  
  dup(256);
  //staptest// dup (256) = -NNNN (EBADF)
  
  dup(-1);
  //staptest// dup (-1) = -NNNN (EBADF)

  dup2(3, 4);
  //staptest// [[[[dup2 (3, 4!!!!dup3 (3, 4, 0x0]]]]) = 4

  dup2(255, 256);
  //staptest// [[[[dup2 (255, 256!!!!dup3 (255, 256, 0x0]]]]) = -NNNN (EBADF)

  /* weird corner case oldfd == newfd */
  dup2(1, 1);
  //staptest// [[[[dup2 (1, 1!!!!fcntl (1, F_GETFL, 0x0]]]]) = 1

  dup2(-1, 4);
  //staptest// [[[[dup2 (-1, 4!!!!dup3 (-1, 4, 0x0]]]]) = -NNNN (EBADF)

  dup2(3, -1);
  //staptest// [[[[dup2 (3, -1!!!!dup3 (3, -1, 0x0]]]]) = -NNNN (EBADF)

#ifdef O_CLOEXEC
  dup3 (4, 5, O_CLOEXEC);
  //staptest// dup3 (4, 5, O_CLOEXEC) = 5

  dup3 (256, 255, O_CLOEXEC);
  //staptest// dup3 (256, 255, O_CLOEXEC) = -NNNN (EBADF)
  
  dup3 (5, 6, 666);
  //staptest// dup3 (5, 6, O_[^ ]+|XXXX) = -NNNN (EINVAL)

  /* corner case not valid for dup3 */
  dup3 (1, 1, O_CLOEXEC);
  //staptest// dup3 (1, 1, O_CLOEXEC) = -NNNN (EINVAL)

  dup3 (-1, 7, 0);
  //staptest// dup3 (-1, 7, 0x0) = -NNNN (EBADF)

  dup3 (3, -1, O_CLOEXEC);
  //staptest// dup3 (3, -1, O_CLOEXEC) = -NNNN (EBADF)

  dup3 (3, 7, -1);
  //staptest// dup3 (3, 7, O_[^ ]+|XXXX) = -NNNN (EINVAL)
#endif

  return 0;
}
Beispiel #13
0
int
xdup3nc(int oldfd, int newfd, int flags)
{
    int rc;

    do {
        rc = dup3(oldfd, newfd, flags);
    } while (rc < 0 && errno == EINTR);

    if (rc < 0)
        die_errno("dup3(%d,%d,0x%x)", oldfd, newfd, (unsigned) flags);

    return rc;
}
Beispiel #14
0
INTERPOSE (dup3, int, int oldfd, int newfd, int flags)
{
  int ret;

  CHECK_INTERPOSE (dup3);

  ret = dup3 (oldfd, newfd, flags);

  copy_our_fd (oldfd, ret);
  copy_our_af (oldfd, ret);


  return ret;
}
Beispiel #15
0
int main(int argc, char* argv[]) {
  pid_t child;
  int status;
  int ret;
  int fd;
  int pipe_fds[2];
  struct rlimit nofile;
  int fd_limit;

  if (argc == 2) {
    atomic_puts("EXIT-SUCCESS");
    return 77;
  }

  /* Various spawning APIs try to close all open file descriptors before
     exec --- via direct close(), or by setting CLOEXEC. Check that
     those don't interfere with rr by closing RR_RESERVED_ROOT_DIR_FD
     or some other essential file descriptor. */
  test_assert(0 == getrlimit(RLIMIT_NOFILE, &nofile));
  if (nofile.rlim_cur == RLIM_INFINITY || nofile.rlim_cur > MAX_FDS) {
    fd_limit = MAX_FDS;
  } else {
    fd_limit = nofile.rlim_cur;
  }
  for (fd = STDERR_FILENO + 1; fd < fd_limit; ++fd) {
    ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
    test_assert(ret == 0 || (ret == -1 && errno == EBADF));
    ret = dup2(STDERR_FILENO, fd);
    test_assert(ret == fd || (ret == -1 && errno == EBADF));
    ret = dup3(STDERR_FILENO, fd, O_CLOEXEC);
    test_assert(ret == fd || (ret == -1 && errno == EBADF));
    ret = close(fd);
    test_assert(ret == 0 || (ret == -1 && errno == EBADF));
  }

  /* Check that syscall buffering still works */
  test_assert(0 == pipe(pipe_fds));
  test_assert(1 == write(pipe_fds[1], "c", 1));

  if (0 == (child = fork())) {
    execl(argv[0], argv[0], "step2", NULL);
  }
  test_assert(child == waitpid(child, &status, 0));
  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);
  return 0;
}
Beispiel #16
0
int uv__dup2_cloexec(int oldfd, int newfd) {
  int r;
#if defined(__FreeBSD__)
  r = dup3(oldfd, newfd, O_CLOEXEC);
  if (r == -1)
    return -errno;
  return r;
#elif defined(__linux__)
  static int no_dup3;
  if (!no_dup3) {
    do
      r = uv__dup3(oldfd, newfd, UV__O_CLOEXEC);
    while (r == -1 && errno == EBUSY);
    if (r != -1)
      return r;
    if (errno != ENOSYS)
      return -errno;
    /* Fall through. */
    no_dup3 = 1;
  }
#endif
  {
    int err;
    do
      r = dup2(oldfd, newfd);
#if defined(__linux__)
    while (r == -1 && errno == EBUSY);
#else
    while (0);  /* Never retry. */
#endif

    if (r == -1)
      return -errno;

    err = uv__cloexec(newfd, 1);
    if (err) {
      uv__close(newfd);
      return err;
    }

    return r;
  }
}
Beispiel #17
0
Datei: dup.c Projekt: szborows/rr
int main(int argc, char* argv[]) {
  int pipe_fds[2];
  int fd;
  char ch;

  test_assert(0 == pipe(pipe_fds));
  test_assert(10 == write(pipe_fds[1], buf, 10));

  fd = dup(pipe_fds[0]);
  test_assert(fd >= 0);
  test_assert(fd != pipe_fds[0] && fd != pipe_fds[1]);
  test_assert(1 == read(fd, &ch, 1));
  test_assert(ch == '0');

  fd = dup2(pipe_fds[0], 0);
  test_assert(fd == 0);
  test_assert(1 == read(fd, &ch, 1));
  test_assert(ch == '1');

  fd = dup3(pipe_fds[0], 49, O_CLOEXEC);
  test_assert(fd == 49);
  test_assert(1 == read(fd, &ch, 1));
  test_assert(ch == '2');
  test_assert(FD_CLOEXEC == fcntl(fd, F_GETFD));

  test_assert(fd == dup2(0, fd));
  test_assert(0 == fcntl(fd, F_GETFD));

  fd = fcntl(pipe_fds[0], F_DUPFD, 49);
  test_assert(fd == 50);
  test_assert(1 == read(fd, &ch, 1));
  test_assert(ch == '3');
  test_assert(0 == fcntl(fd, F_GETFD));

  fd = fcntl(pipe_fds[0], F_DUPFD_CLOEXEC, 49);
  test_assert(fd == 51);
  test_assert(1 == read(fd, &ch, 1));
  test_assert(ch == '4');
  test_assert(FD_CLOEXEC == fcntl(fd, F_GETFD));

  atomic_puts("EXIT-SUCCESS");
  return 0;
}
Beispiel #18
0
JNIEXPORT jint JNICALL xnio_native(dup2)(JNIEnv *env, jclass clazz, jint oldFD, jint newFD, jobject preserve) {
    if (dup3) {
        if (dup3(oldFD, newFD, O_CLOEXEC) < 0) {
            return -errno;
        } else {
            return 0;
        }
    } else {
        if (dup2(oldFD, newFD) < 0) {
            return -errno;
        }
        if (fcntl(newFD, F_SETFD, FD_CLOEXEC) == -1) {
            int code = errno;
            close(newFD);
            return -code;
        }
        return 0;
    }
}
Beispiel #19
0
ATF_TC_BODY(dup3_err, tc)
{
	int fd;

	fd = open("/etc/passwd", O_RDONLY);
	ATF_REQUIRE(fd >= 0);

	errno = 0;
#if defined(__FreeBSD__) || defined(__linux__)
	/*
	 * FreeBSD and linux return EINVAL, because...
	 *
	 * [EINVAL] The oldd argument is equal to the newd argument.
	 */
	ATF_REQUIRE(dup3(fd, fd, O_CLOEXEC) == -1);
#else
	ATF_REQUIRE(dup3(fd, fd, O_CLOEXEC) != -1);
#endif

	errno = 0;
#if defined(__FreeBSD__) || defined(__linux__)
	ATF_REQUIRE_ERRNO(EINVAL, dup3(-1, -1, O_CLOEXEC) == -1);
	ATF_REQUIRE_ERRNO(EBADF, dup3(fd, -1, O_CLOEXEC) == -1);
#else
	ATF_REQUIRE_ERRNO(EBADF, dup3(-1, -1, O_CLOEXEC) == -1);
#endif

	errno = 0;
	ATF_REQUIRE_ERRNO(EBADF, dup3(fd, -1, O_CLOEXEC) == -1);

	errno = 0;
	ATF_REQUIRE_ERRNO(EBADF, dup3(-1, fd, O_CLOEXEC) == -1);

	errno = 0;
	ATF_REQUIRE_ERRNO(EINVAL, dup3(fd, 1, O_NOFOLLOW) == -1);

	(void)close(fd);
}
Beispiel #20
0
int
dup3 (int oldfd, int newfd, int flags)
{
#if HAVE_DUP3
# undef dup3
  /* Try the system call first, if it exists.  (We may be running with a glibc
     that has the function but with an older kernel that lacks it.)  */
  {
    /* Cache the information whether the system call really exists.  */
    static int have_dup3_really; /* 0 = unknown, 1 = yes, -1 = no */
    if (have_dup3_really >= 0)
      {
        int result = dup3 (oldfd, newfd, flags);
        if (!(result < 0 && errno == ENOSYS))
          {
            have_dup3_really = 1;
#if REPLACE_FCHDIR
            if (0 <= result)
              result = _gl_register_dup (oldfd, newfd);
#endif
            return result;
          }
        have_dup3_really = -1;
      }
  }
#endif

  if (newfd < 0 || newfd >= getdtablesize () || fcntl (oldfd, F_GETFD) == -1)
    {
      errno = EBADF;
      return -1;
    }

  if (newfd == oldfd)
    {
      errno = EINVAL;
      return -1;
    }

  /* Check the supported flags.
     Note that O_NONBLOCK is not supported, because setting it on newfd
     would implicitly also set it on oldfd.  */
  if ((flags & ~(O_CLOEXEC | O_BINARY | O_TEXT)) != 0)
    {
      errno = EINVAL;
      return -1;
    }

  if (flags & O_CLOEXEC)
    {
      int result;
      close (newfd);
      result = fcntl (oldfd, F_DUPFD_CLOEXEC, newfd);
      if (newfd < result)
        {
          close (result);
          errno = EIO;
          result = -1;
        }
      if (result < 0)
        return -1;
    }
  else if (dup2 (oldfd, newfd) < 0)
    return -1;

#if O_BINARY
  if (flags & O_BINARY)
    setmode (newfd, O_BINARY);
  else if (flags & O_TEXT)
    setmode (newfd, O_TEXT);
#endif

  return newfd;
}
Beispiel #21
0
static apr_status_t file_dup(apr_file_t **new_file, 
                             apr_file_t *old_file, apr_pool_t *p,
                             int which_dup)
{
    int rv;
#ifdef HAVE_DUP3
    int flags = 0;
#endif

    if (which_dup == 2) {
        if ((*new_file) == NULL) {
            /* We can't dup2 unless we have a valid new_file */
            return APR_EINVAL;
        }
#ifdef HAVE_DUP3
        if (!((*new_file)->flags & (APR_FOPEN_NOCLEANUP|APR_INHERIT)))
            flags |= O_CLOEXEC;
        rv = dup3(old_file->filedes, (*new_file)->filedes, flags);
#else
        rv = dup2(old_file->filedes, (*new_file)->filedes);
        if (!((*new_file)->flags & (APR_FOPEN_NOCLEANUP|APR_INHERIT))) {
            int flags;

            if (rv == -1)
                return errno;

            if ((flags = fcntl((*new_file)->filedes, F_GETFD)) == -1)
                return errno;

            flags |= FD_CLOEXEC;
            if (fcntl((*new_file)->filedes, F_SETFD, flags) == -1)
                return errno;

        }
#endif
    } else {
        rv = dup(old_file->filedes);
    }

    if (rv == -1)
        return errno;
    
    if (which_dup == 1) {
        (*new_file) = (apr_file_t *)apr_pcalloc(p, sizeof(apr_file_t));
        (*new_file)->pool = p;
        (*new_file)->filedes = rv;
    }

    (*new_file)->fname = apr_pstrdup(p, old_file->fname);
    (*new_file)->buffered = old_file->buffered;

    /* If the existing socket in a dup2 is already buffered, we
     * have an existing and valid (hopefully) mutex, so we don't
     * want to create it again as we could leak!
     */
#if APR_HAS_THREADS
    if ((*new_file)->buffered && !(*new_file)->thlock && old_file->thlock) {
        apr_thread_mutex_create(&((*new_file)->thlock),
                                APR_THREAD_MUTEX_DEFAULT, p);
    }
#endif
    /* As above, only create the buffer if we haven't already
     * got one.
     */
    if ((*new_file)->buffered && !(*new_file)->buffer) {
        (*new_file)->buffer = apr_palloc(p, old_file->bufsize);
        (*new_file)->bufsize = old_file->bufsize;
    }

    /* this is the way dup() works */
    (*new_file)->blocking = old_file->blocking; 

    /* make sure unget behavior is consistent */
    (*new_file)->ungetchar = old_file->ungetchar;

    /* apr_file_dup2() retains the original cleanup, reflecting 
     * the existing inherit and nocleanup flags.  This means, 
     * that apr_file_dup2() cannot be called against an apr_file_t
     * already closed with apr_file_close, because the expected
     * cleanup was already killed.
     */
    if (which_dup == 2) {
        return APR_SUCCESS;
    }

    /* apr_file_dup() retains all old_file flags with the exceptions
     * of APR_INHERIT and APR_FOPEN_NOCLEANUP.
     * The user must call apr_file_inherit_set() on the dupped 
     * apr_file_t when desired.
     */
    (*new_file)->flags = old_file->flags
                       & ~(APR_INHERIT | APR_FOPEN_NOCLEANUP);

    apr_pool_cleanup_register((*new_file)->pool, (void *)(*new_file),
                              apr_unix_file_cleanup, 
                              apr_unix_child_file_cleanup);
#ifndef WAITIO_USES_POLL
    /* Start out with no pollset.  apr_wait_for_io_or_timeout() will
     * initialize the pollset if needed.
     */
    (*new_file)->pollset = NULL;
#endif
    return APR_SUCCESS;
}
Beispiel #22
0
void nsexec(void)
{
	int pipenum;

	// If we don't have init pipe, then just return to the go routine,
	// we'll only have init pipe for start or exec
	pipenum = get_init_pipe();
	if (pipenum == -1) {
		return;
	}

	// Retrieve the netlink header
	struct nlmsghdr nl_msg_hdr;
	int		len;

	if ((len = read(pipenum, &nl_msg_hdr, NLMSG_HDRLEN)) != NLMSG_HDRLEN) {
		pr_perror("Invalid netlink header length %d", len);
		exit(1);
	}

	if (nl_msg_hdr.nlmsg_type == NLMSG_ERROR) {
		pr_perror("Failed to read netlink message");
		exit(1);
	}

	if (nl_msg_hdr.nlmsg_type != INIT_MSG) {
		pr_perror("Unexpected msg type %d", nl_msg_hdr.nlmsg_type);
		exit(1);
	}

	// Retrieve data
	int  nl_total_size = NLMSG_PAYLOAD(&nl_msg_hdr, 0);
	char data[nl_total_size];

	if ((len = read(pipenum, data, nl_total_size)) != nl_total_size) {
		pr_perror("Failed to read netlink payload, %d != %d", len,
			  nl_total_size);
		exit(1);
	}

	jmp_buf	env;
	int	syncpipe[2] = {-1, -1};
	struct	nsenter_config config = process_nl_attributes(pipenum,
						data, nl_total_size);

	// required clone_flags to be passed
	if (config.cloneflags == -1) {
		pr_perror("Missing clone_flags");
		exit(1);
	}
	// prepare sync pipe between parent and child. We need this to let the
	// child know that the parent has finished setting up
	if (pipe(syncpipe) != 0) {
		pr_perror("Failed to setup sync pipe between parent and child");
		exit(1);
	}

	if (setjmp(env) == 1) {
		// Child
		uint8_t s = 0;
		int	consolefd = config.consolefd;

		// close the writing side of pipe
		close(syncpipe[1]);

		// sync with parent
		if ((read(syncpipe[0], &s, 1) != 1) || (s != 1)) {
			pr_perror("Failed to read sync byte from parent");
			exit(1);
		}

		if (setsid() == -1) {
			pr_perror("setsid failed");
			exit(1);
		}

		if (setuid(0) == -1) {
			pr_perror("setuid failed");
			exit(1);
		}

		if (setgid(0) == -1) {
			pr_perror("setgid failed");
			exit(1);
		}
    
		if (setgroups(0, NULL) == -1) {
			pr_perror("setgroups failed");
			exit(1);
		}

		if (consolefd != -1) {
			if (ioctl(consolefd, TIOCSCTTY, 0) == -1) {
				pr_perror("ioctl TIOCSCTTY failed");
				exit(1);
			}
			if (dup3(consolefd, STDIN_FILENO, 0) != STDIN_FILENO) {
				pr_perror("Failed to dup stdin");
				exit(1);
			}
			if (dup3(consolefd, STDOUT_FILENO, 0) != STDOUT_FILENO) {
				pr_perror("Failed to dup stdout");
				exit(1);
			}
			if (dup3(consolefd, STDERR_FILENO, 0) != STDERR_FILENO) {
				pr_perror("Failed to dup stderr");
				exit(1);
			}
		}

		// Finish executing, let the Go runtime take over.
		return;
	}

	// Parent
	start_child(pipenum, &env, syncpipe, &config);
}
Beispiel #23
0
int dup2 (int fd, int fd2) {
	return dup3 (fd, fd2, 0);
}
Beispiel #24
0
int
VanillaProc::setupOOMEvent(const std::string &cgroup_string)
{
#if !(defined(HAVE_EVENTFD) && defined(HAVE_EXT_LIBCGROUP))
	// Shut the compiler up.
	cgroup_string.size();
	return 0;
#else
	// Initialize the event descriptor
	int tmp_efd = eventfd(0, EFD_CLOEXEC);
	if (tmp_efd == -1) {
		dprintf(D_ALWAYS,
			"Unable to create new event FD for starter: %u %s\n",
			errno, strerror(errno));
		return 1;
	}

	// Find the memcg location on disk
	void * handle = NULL;
	struct cgroup_mount_point mount_info;
	int ret = cgroup_get_controller_begin(&handle, &mount_info);
	std::stringstream oom_control;
	std::stringstream event_control;
	bool found_memcg = false;
	while (ret == 0) {
		if (strcmp(mount_info.name, MEMORY_CONTROLLER_STR) == 0) {
			found_memcg = true;
			oom_control << mount_info.path << "/";
			event_control << mount_info.path << "/";
			break;
		}
		cgroup_get_controller_next(&handle, &mount_info);
	}
	if (!found_memcg && (ret != ECGEOF)) {
		dprintf(D_ALWAYS,
			"Error while locating memcg controller for starter: %u %s\n",
			ret, cgroup_strerror(ret));
		return 1;
	}
	cgroup_get_controller_end(&handle);
	if (found_memcg == false) {
		dprintf(D_ALWAYS,
			"Memcg is not available; OOM notification disabled for starter.\n");
		return 1;
	}

	// Finish constructing the location of the control files
	oom_control << cgroup_string << "/memory.oom_control";
	std::string oom_control_str = oom_control.str();
	event_control << cgroup_string << "/cgroup.event_control";
	std::string event_control_str = event_control.str();

	// Open the oom_control and event control files
	TemporaryPrivSentry sentry(PRIV_ROOT);
	m_oom_fd = open(oom_control_str.c_str(), O_RDONLY | O_CLOEXEC);
	if (m_oom_fd == -1) {
		dprintf(D_ALWAYS,
			"Unable to open the OOM control file for starter: %u %s\n",
			errno, strerror(errno));
		return 1;
	}
	int event_ctrl_fd = open(event_control_str.c_str(), O_WRONLY | O_CLOEXEC);
	if (event_ctrl_fd == -1) {
		dprintf(D_ALWAYS,
			"Unable to open event control for starter: %u %s\n",
			errno, strerror(errno));
		return 1;
	}

	// Inform Linux we will be handling the OOM events for this container.
	int oom_fd2 = open(oom_control_str.c_str(), O_WRONLY | O_CLOEXEC);
	if (oom_fd2 == -1) {
		dprintf(D_ALWAYS,
			"Unable to open the OOM control file for writing for starter: %u %s\n",
			errno, strerror(errno));
		close(event_ctrl_fd);
		return 1;
	}
	const char limits [] = "1";
        ssize_t nwritten = full_write(oom_fd2, &limits, 1);
	if (nwritten < 0) {
		/* Newer kernels return EINVAL if you attempt to enable OOM management
		 * on a cgroup where use_hierarchy is set to 1 and it is not the parent
		 * cgroup.
		 *
		 * This is a common setup, so we log and move along.
		 *
		 * See also #4435.
		 */
		if (errno == EINVAL)
		{
			dprintf(D_FULLDEBUG, "Unable to setup OOM killer management because"
				" memory.use_hierarchy is enabled for this cgroup; consider"
				" disabling it for this host or set BASE_CGROUP=/.  The hold"
				" message for an OOM event may not be reliably set.\n");
		}
		else
		{
			dprintf(D_ALWAYS, "Failure when attempting to enable OOM killer "
				" management for this job (errno=%d, %s).\n", errno, strerror(errno));
			close(event_ctrl_fd);
			close(oom_fd2);
			close(tmp_efd);
			return 1;
		}

	}
	close(oom_fd2);

	// Create the subscription string:
	std::stringstream sub_ss;
	sub_ss << tmp_efd << " " << m_oom_fd;
	std::string sub_str = sub_ss.str();

	if ((nwritten = full_write(event_ctrl_fd, sub_str.c_str(), sub_str.size())) < 0) {
		dprintf(D_ALWAYS,
			"Unable to write into event control file for starter: %u %s\n",
			errno, strerror(errno));
		close(event_ctrl_fd);
		close(tmp_efd);
		return 1;
	}
	close(event_ctrl_fd);

	// Fool DC into talking to the eventfd
	int pipes[2]; pipes[0] = -1; pipes[1] = -1;
	int fd_to_replace = -1;
	if (!daemonCore->Create_Pipe(pipes, true) || pipes[0] == -1) {
		dprintf(D_ALWAYS, "Unable to create a DC pipe\n");
		close(tmp_efd);
		close(m_oom_fd);
		m_oom_fd = -1;
		return 1;
	}
	if (!daemonCore->Get_Pipe_FD(pipes[0], &fd_to_replace) || fd_to_replace == -1) {
		dprintf(D_ALWAYS, "Unable to lookup pipe's FD\n");
		close(tmp_efd);
		close(m_oom_fd); m_oom_fd = -1;
		daemonCore->Close_Pipe(pipes[0]);
		daemonCore->Close_Pipe(pipes[1]);
		return 1;
	}
	dup3(tmp_efd, fd_to_replace, O_CLOEXEC);
	close(tmp_efd);
	m_oom_efd = pipes[0];
	m_oom_efd2 = pipes[1];

	// Inform DC we want to recieve notifications from this FD.
	if (-1 == daemonCore->Register_Pipe(pipes[0],"OOM event fd", static_cast<PipeHandlercpp>(&VanillaProc::outOfMemoryEvent),"OOM Event Handler",this,HANDLE_READ))
	{
		dprintf(D_ALWAYS, "Failed to register OOM event FD pipe.\n");
		daemonCore->Close_Pipe(pipes[0]);
		daemonCore->Close_Pipe(pipes[1]);
		m_oom_fd = -1;
		m_oom_efd = -1;
		m_oom_efd2 = -1;
	}
	dprintf(D_FULLDEBUG, "Subscribed the starter to OOM notification for this cgroup; jobs triggering an OOM will be put on hold.\n");
	return 0;
#endif
}
Beispiel #25
0
int
main(int __unused argc, char __unused *argv[])
{
	struct rlimit rlp;
	int orgfd, fd1, fd2, test = 0;

	orgfd = getafile();

	printf("1..32\n");

	/* If dup(2) ever work? */
	if ((fd1 = dup(orgfd)) < 0)
		err(1, "dup");
	printf("ok %d - dup(2) works\n", ++test);

	/* Set close-on-exec */
	if (fcntl(fd1, F_SETFD, 1) != 0)
		err(1, "fcntl(F_SETFD)");

	/* If dup2(2) ever work? */
	if ((fd2 = dup2(fd1, fd1 + 1)) < 0)
		err(1, "dup2");
	printf("ok %d - dup2(2) works\n", ++test);

	/* Do we get the right fd? */
	++test;
	if (fd2 != fd1 + 1)
		printf("no ok %d - dup2(2) didn't give us the right fd\n",
		    test);
	else
		printf("ok %d - dup2(2) returned a correct fd\n", test);

	/* Was close-on-exec cleared? */
	++test;
	if (fcntl(fd2, F_GETFD) != 0)
		printf("not ok %d - dup2(2) didn't clear close-on-exec\n",
		    test);
	else
		printf("ok %d - dup2(2) cleared close-on-exec\n", test);

	/*
	 * Dup to itself.
	 *
	 * We're testing a small tweak in dup2 semantics.
	 * Normally dup and dup2 will clear the close-on-exec
	 * flag on the new fd (which appears to be an implementation
	 * mistake from start and not some planned behavior).
	 * In today's implementations of dup and dup2 we have to make
	 * an effort to really clear that flag.  But all tested
	 * implementations of dup2 have another tweak.  If we
	 * dup2(old, new) when old == new, the syscall short-circuits
	 * and returns early (because there is no need to do all the
	 * work (and there is a risk for serious mistakes)).
	 * So although the docs say that dup2 should "take 'old',
	 * close 'new' perform a dup(2) of 'old' into 'new'"
	 * the docs are not really followed because close-on-exec
	 * is not cleared on 'new'.
	 *
	 * Since everyone has this bug, we pretend that this is
	 * the way it is supposed to be and test here that it really
	 * works that way.
	 *
	 * This is a fine example on where two separate implementation
	 * fuckups take out each other and make the end-result the way
	 * it was meant to be.
	 */
	if ((fd2 = dup2(fd1, fd1)) < 0)
		err(1, "dup2");
	printf("ok %d - dup2(2) to itself works\n", ++test);

	/* Do we get the right fd? */
	++test;
	if (fd2 != fd1)
		printf("not ok %d - dup2(2) didn't give us the right fd\n",
		    test);
	else
		printf("ok %d - dup2(2) to itself returned a correct fd\n",
		    test);

	/* Was close-on-exec cleared? */
	++test;
	if (fcntl(fd2, F_GETFD) == 0)
		printf("not ok %d - dup2(2) cleared close-on-exec\n", test);
	else
		printf("ok %d - dup2(2) didn't clear close-on-exec\n", test);

	/* Does fcntl(F_DUPFD) work? */
	if ((fd2 = fcntl(fd1, F_DUPFD, 10)) < 0)
		err(1, "fcntl(F_DUPFD)");
	if (fd2 < 10)
		printf("not ok %d - fcntl(F_DUPFD) returned wrong fd %d\n",
		    ++test, fd2);
	else
		printf("ok %d - fcntl(F_DUPFD) works\n", ++test);

	/* Was close-on-exec cleared? */
	++test;
        if (fcntl(fd2, F_GETFD) != 0)
		printf(
		    "not ok %d - fcntl(F_DUPFD) didn't clear close-on-exec\n",
		    test);
	else
		printf("ok %d - fcntl(F_DUPFD) cleared close-on-exec\n", test);

	++test;
	if (getrlimit(RLIMIT_NOFILE, &rlp) < 0)
		err(1, "getrlimit");
	if ((fd2 = dup2(fd1, rlp.rlim_cur + 1)) >= 0)
		printf("not ok %d - dup2(2) bypassed NOFILE limit\n", test);
	else
		printf("ok %d - dup2(2) didn't bypass NOFILE limit\n", test);

	/* If fcntl(F_DUP2FD) ever work? */
	if ((fd2 = fcntl(fd1, F_DUP2FD, fd1 + 1)) < 0)
		err(1, "fcntl(F_DUP2FD)");
	printf("ok %d - fcntl(F_DUP2FD) works\n", ++test);

	/* Do we get the right fd? */
	++test;
	if (fd2 != fd1 + 1)
		printf(
		    "no ok %d - fcntl(F_DUP2FD) didn't give us the right fd\n",
		    test);
	else
		printf("ok %d - fcntl(F_DUP2FD) returned a correct fd\n",
		    test);

	/* Was close-on-exec cleared? */
	++test;
	if (fcntl(fd2, F_GETFD) != 0)
		printf(
		    "not ok %d - fcntl(F_DUP2FD) didn't clear close-on-exec\n",
		    test);
	else
		printf("ok %d - fcntl(F_DUP2FD) cleared close-on-exec\n",
		    test);

	/* Dup to itself */
	if ((fd2 = fcntl(fd1, F_DUP2FD, fd1)) < 0)
		err(1, "fcntl(F_DUP2FD)");
	printf("ok %d - fcntl(F_DUP2FD) to itself works\n", ++test);

	/* Do we get the right fd? */
	++test;
	if (fd2 != fd1)
		printf(
		    "not ok %d - fcntl(F_DUP2FD) didn't give us the right fd\n",
		    test);
	else
		printf(
		    "ok %d - fcntl(F_DUP2FD) to itself returned a correct fd\n",
		    test);

	/* Was close-on-exec cleared? */
	++test;
	if (fcntl(fd2, F_GETFD) == 0)
		printf("not ok %d - fcntl(F_DUP2FD) cleared close-on-exec\n",
		    test);
	else
		printf("ok %d - fcntl(F_DUP2FD) didn't clear close-on-exec\n",
		    test);

	++test;
	if (getrlimit(RLIMIT_NOFILE, &rlp) < 0)
		err(1, "getrlimit");
	if ((fd2 = fcntl(fd1, F_DUP2FD, rlp.rlim_cur + 1)) >= 0)
		printf("not ok %d - fcntl(F_DUP2FD) bypassed NOFILE limit\n",
		    test);
	else
		printf("ok %d - fcntl(F_DUP2FD) didn't bypass NOFILE limit\n",
		    test);

	/* Does fcntl(F_DUPFD_CLOEXEC) work? */
	if ((fd2 = fcntl(fd1, F_DUPFD_CLOEXEC, 10)) < 0)
		err(1, "fcntl(F_DUPFD_CLOEXEC)");
	if (fd2 < 10)
		printf("not ok %d - fcntl(F_DUPFD_CLOEXEC) returned wrong fd %d\n",
		    ++test, fd2);
	else
		printf("ok %d - fcntl(F_DUPFD_CLOEXEC) works\n", ++test);

	/* Was close-on-exec cleared? */
	++test;
        if (fcntl(fd2, F_GETFD) != 1)
		printf(
		    "not ok %d - fcntl(F_DUPFD_CLOEXEC) didn't set close-on-exec\n",
		    test);
	else
		printf("ok %d - fcntl(F_DUPFD_CLOEXEC) set close-on-exec\n",
		    test);

	/* If fcntl(F_DUP2FD_CLOEXEC) ever work? */
	if ((fd2 = fcntl(fd1, F_DUP2FD_CLOEXEC, fd1 + 1)) < 0)
		err(1, "fcntl(F_DUP2FD_CLOEXEC)");
	printf("ok %d - fcntl(F_DUP2FD_CLOEXEC) works\n", ++test);

	/* Do we get the right fd? */
	++test;
	if (fd2 != fd1 + 1)
		printf(
		    "no ok %d - fcntl(F_DUP2FD_CLOEXEC) didn't give us the right fd\n",
		    test);
	else
		printf("ok %d - fcntl(F_DUP2FD_CLOEXEC) returned a correct fd\n",
		    test);

	/* Was close-on-exec set? */
	++test;
	if (fcntl(fd2, F_GETFD) != FD_CLOEXEC)
		printf(
		    "not ok %d - fcntl(F_DUP2FD_CLOEXEC) didn't set close-on-exec\n",
		    test);
	else
		printf("ok %d - fcntl(F_DUP2FD_CLOEXEC) set close-on-exec\n",
		    test);

	/*
	 * It is unclear what F_DUP2FD_CLOEXEC should do when duplicating a
	 * file descriptor onto itself.
	 */

	++test;
	if (getrlimit(RLIMIT_NOFILE, &rlp) < 0)
		err(1, "getrlimit");
	if ((fd2 = fcntl(fd1, F_DUP2FD_CLOEXEC, rlp.rlim_cur + 1)) >= 0)
		printf("not ok %d - fcntl(F_DUP2FD_CLOEXEC) bypassed NOFILE limit\n",
		    test);
	else
		printf("ok %d - fcntl(F_DUP2FD_CLOEXEC) didn't bypass NOFILE limit\n",
		    test);

	/* Does dup3(O_CLOEXEC) ever work? */
	if ((fd2 = dup3(fd1, fd1 + 1, O_CLOEXEC)) < 0)
		err(1, "dup3(O_CLOEXEC)");
	printf("ok %d - dup3(O_CLOEXEC) works\n", ++test);

	/* Do we get the right fd? */
	++test;
	if (fd2 != fd1 + 1)
		printf(
		    "no ok %d - dup3(O_CLOEXEC) didn't give us the right fd\n",
		    test);
	else
		printf("ok %d - dup3(O_CLOEXEC) returned a correct fd\n",
		    test);

	/* Was close-on-exec set? */
	++test;
	if (fcntl(fd2, F_GETFD) != FD_CLOEXEC)
		printf(
		    "not ok %d - dup3(O_CLOEXEC) didn't set close-on-exec\n",
		    test);
	else
		printf("ok %d - dup3(O_CLOEXEC) set close-on-exec\n",
		    test);

	/* Does dup3(0) ever work? */
	if ((fd2 = dup3(fd1, fd1 + 1, 0)) < 0)
		err(1, "dup3(0)");
	printf("ok %d - dup3(0) works\n", ++test);

	/* Do we get the right fd? */
	++test;
	if (fd2 != fd1 + 1)
		printf(
		    "no ok %d - dup3(0) didn't give us the right fd\n",
		    test);
	else
		printf("ok %d - dup3(0) returned a correct fd\n",
		    test);

	/* Was close-on-exec cleared? */
	++test;
	if (fcntl(fd2, F_GETFD) != 0)
		printf(
		    "not ok %d - dup3(0) didn't clear close-on-exec\n",
		    test);
	else
		printf("ok %d - dup3(0) cleared close-on-exec\n",
		    test);

	/* dup3() does not allow duplicating to the same fd */
	++test;
	if (dup3(fd1, fd1, O_CLOEXEC) != -1)
		printf(
		    "not ok %d - dup3(fd1, fd1, O_CLOEXEC) succeeded\n", test);
	else
		printf("ok %d - dup3(fd1, fd1, O_CLOEXEC) failed\n", test);

	++test;
	if (dup3(fd1, fd1, 0) != -1)
		printf(
		    "not ok %d - dup3(fd1, fd1, 0) succeeded\n", test);
	else
		printf("ok %d - dup3(fd1, fd1, 0) failed\n", test);

	++test;
	if (getrlimit(RLIMIT_NOFILE, &rlp) < 0)
		err(1, "getrlimit");
	if ((fd2 = dup3(fd1, rlp.rlim_cur + 1, O_CLOEXEC)) >= 0)
		printf("not ok %d - dup3(O_CLOEXEC) bypassed NOFILE limit\n",
		    test);
	else
		printf("ok %d - dup3(O_CLOEXEC) didn't bypass NOFILE limit\n",
		    test);

	return (0);
}
Beispiel #26
0
int
VanillaProc::setupOOMEvent(const std::string &cgroup_string)
{
#if !(defined(HAVE_EVENTFD) && defined(HAVE_EXT_LIBCGROUP))
	// Shut the compiler up.
	cgroup_string.size();
	return 0;
#else
	// Initialize the event descriptor
	m_oom_efd = eventfd(0, EFD_CLOEXEC);
	if (m_oom_efd == -1) {
		dprintf(D_ALWAYS,
			"Unable to create new event FD for starter: %u %s\n",
			errno, strerror(errno));
		return 1;
	}

	// Find the memcg location on disk
	void * handle = NULL;
	struct cgroup_mount_point mount_info;
	int ret = cgroup_get_controller_begin(&handle, &mount_info);
	std::stringstream oom_control;
	std::stringstream event_control;
	bool found_memcg = false;
	while (ret == 0) {
		if (strcmp(mount_info.name, MEMORY_CONTROLLER_STR) == 0) {
			found_memcg = true;
			oom_control << mount_info.path << "/";
			event_control << mount_info.path << "/";
			break;
		}
		cgroup_get_controller_next(&handle, &mount_info);
	}
	if (!found_memcg && (ret != ECGEOF)) {
		dprintf(D_ALWAYS,
			"Error while locating memcg controller for starter: %u %s\n",
			ret, cgroup_strerror(ret));
		return 1;
	}
	cgroup_get_controller_end(&handle);
	if (found_memcg == false) {
		dprintf(D_ALWAYS,
			"Memcg is not available; OOM notification disabled for starter.\n");
		return 1;
	}

	// Finish constructing the location of the control files
	oom_control << cgroup_string << "/memory.oom_control";
	std::string oom_control_str = oom_control.str();
	event_control << cgroup_string << "/cgroup.event_control";
	std::string event_control_str = event_control.str();

	// Open the oom_control and event control files
	TemporaryPrivSentry sentry(PRIV_ROOT);
	m_oom_fd = open(oom_control_str.c_str(), O_RDONLY | O_CLOEXEC);
	if (m_oom_fd == -1) {
		dprintf(D_ALWAYS,
			"Unable to open the OOM control file for starter: %u %s\n",
			errno, strerror(errno));
		return 1;
	}
	int event_ctrl_fd = open(event_control_str.c_str(), O_WRONLY | O_CLOEXEC);
	if (event_ctrl_fd == -1) {
		dprintf(D_ALWAYS,
			"Unable to open event control for starter: %u %s\n",
			errno, strerror(errno));
		return 1;
	}

	// Inform Linux we will be handling the OOM events for this container.
	int oom_fd2 = open(oom_control_str.c_str(), O_WRONLY | O_CLOEXEC);
	if (oom_fd2 == -1) {
		dprintf(D_ALWAYS,
			"Unable to open the OOM control file for writing for starter: %u %s\n",
			errno, strerror(errno));
		close(event_ctrl_fd);
		return 1;
	}
	const char limits [] = "1";
        ssize_t nwritten = full_write(oom_fd2, &limits, 1);
	if (nwritten < 0) {
		dprintf(D_ALWAYS,
			"Unable to set OOM control to %s for starter: %u %s\n",
				limits, errno, strerror(errno));
		close(event_ctrl_fd);
		close(oom_fd2);
		return 1;
	}
	close(oom_fd2);

	// Create the subscription string:
	std::stringstream sub_ss;
	sub_ss << m_oom_efd << " " << m_oom_fd;
	std::string sub_str = sub_ss.str();

	if ((nwritten = full_write(event_ctrl_fd, sub_str.c_str(), sub_str.size())) < 0) {
		dprintf(D_ALWAYS,
			"Unable to write into event control file for starter: %u %s\n",
			errno, strerror(errno));
		close(event_ctrl_fd);
		return 1;
	}
	close(event_ctrl_fd);

	// Fool DC into talking to the eventfd
	int pipes[2]; pipes[0] = -1; pipes[1] = -1;
	int fd_to_replace = -1;
	if (daemonCore->Create_Pipe(pipes, true) == -1 || pipes[0] == -1) {
		dprintf(D_ALWAYS, "Unable to create a DC pipe\n");
		close(m_oom_efd);
		m_oom_efd = -1;
		close(m_oom_fd);
		m_oom_fd = -1;
		return 1;
	}
	if ( daemonCore->Get_Pipe_FD(pipes[0], &fd_to_replace) == -1 || fd_to_replace == -1) {
		dprintf(D_ALWAYS, "Unable to lookup pipe's FD\n");
		close(m_oom_efd); m_oom_efd = -1;
		close(m_oom_fd); m_oom_fd = -1;
		daemonCore->Close_Pipe(pipes[0]);
		daemonCore->Close_Pipe(pipes[1]);
		return 1;
	}
	dup3(m_oom_efd, fd_to_replace, O_CLOEXEC);
	close(m_oom_efd);
	m_oom_efd = pipes[0];

	// Inform DC we want to recieve notifications from this FD.
	daemonCore->Register_Pipe(pipes[0],"OOM event fd", static_cast<PipeHandlercpp>(&VanillaProc::outOfMemoryEvent),"OOM Event Handler",this,HANDLE_READ);
	return 0;
#endif
}