--- /dev/null
+/*
+ * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
+ * Copyright (C) 2014 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License, version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This program 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 General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <paths.h>
+#include <fcntl.h>
+#include <wait.h>
+#include <stdlib.h>
+
+#include <urcu/system.h>
+
+#include <src/common/daemonize.h>
+#include <src/common/error.h>
+
+int lttng_daemonize(pid_t *child_ppid, int *completion_flag,
+ int close_fds)
+{
+ int ret;
+ pid_t pid;
+
+ /* Get parent pid of this process. */
+ *child_ppid = getppid();
+
+ pid = fork();
+ if (pid < 0) {
+ PERROR("fork");
+ goto error;
+ } else if (pid == 0) {
+ int fd;
+ pid_t sid;
+
+ /* Child */
+
+ /*
+ * Get the newly created parent pid so we can signal
+ * that process when we are ready to operate.
+ */
+ *child_ppid = getppid();
+
+ sid = setsid();
+ if (sid < 0) {
+ PERROR("setsid");
+ goto error;
+ }
+
+ /*
+ * Try to change directory to /. If we can't well at
+ * least notify.
+ */
+ ret = chdir("/");
+ if (ret < 0) {
+ PERROR("chdir");
+ }
+
+ if (close_fds) {
+ fd = open(_PATH_DEVNULL, O_RDWR, 0);
+ if (fd < 0) {
+ PERROR("open %s", _PATH_DEVNULL);
+ /*
+ * Let 0, 1 and 2 open since we can't
+ * bind them to /dev/null.
+ */
+ } else {
+ (void) dup2(fd, STDIN_FILENO);
+ (void) dup2(fd, STDOUT_FILENO);
+ (void) dup2(fd, STDERR_FILENO);
+ if (fd > 2) {
+ ret = close(fd);
+ if (ret < 0) {
+ PERROR("close");
+ }
+ }
+ }
+ }
+ goto end;
+ } else {
+ /* Parent */
+
+ /*
+ * Waiting for child to notify this parent that it can
+ * exit. Note that sleep() is interrupted before the 1
+ * second delay as soon as the signal is received, so it
+ * will not cause visible delay for the user.
+ */
+ while (!CMM_LOAD_SHARED(*completion_flag)) {
+ int status;
+ pid_t ret;
+
+ /*
+ * Check if child exists without blocking. If
+ * so, we have to stop this parent process and
+ * return an error.
+ */
+ ret = waitpid(pid, &status, WNOHANG);
+ if (ret < 0 || (ret != 0 && WIFEXITED(status))) {
+ /* The child exited somehow or was not valid. */
+ goto error;
+ }
+ sleep(1);
+ }
+
+ /*
+ * From this point on, the parent can exit and the child
+ * is now an operationnal session daemon ready to serve
+ * clients and applications.
+ */
+ exit(EXIT_SUCCESS);
+ }
+
+end:
+ return 0;
+
+error:
+ return -1;
+}
--- /dev/null
+#ifndef LTTNG_DAEMONIZE_H
+#define LTTNG_DAEMONIZE_H
+
+/*
+ * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
+ * Copyright (C) 2014 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License, version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This program 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 General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <unistd.h>
+
+/*
+ * Daemonize this process by forking and making the parent wait for the child
+ * to signal it indicating readiness. Once received, the parent successfully
+ * quits.
+ *
+ * The child process undergoes the same action that daemon(3) does meaning
+ * setsid, chdir, and dup /dev/null into 0, 1 and 2.
+ *
+ * Return 0 on success else -1 on error.
+ */
+int lttng_daemonize(pid_t *child_ppid, int *completion_flag,
+ int close_fds);
+
+#endif /* LTTNG_DAEMONIZE_H */