Tests: Fix: Use '.logfile' instead of '.log' for test app output
[lttng-tools.git] / src / common / daemonize.cpp
CommitLineData
99ed9c43 1/*
ab5be9fa
MJ
2 * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
3 * Copyright (C) 2014 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
99ed9c43 4 *
ab5be9fa 5 * SPDX-License-Identifier: GPL-2.0-only
99ed9c43 6 *
99ed9c43
MD
7 */
8
6c1c0768 9#define _LGPL_SOURCE
c9e313bc 10#include <common/compat/paths.hpp>
28ab034a
JG
11#include <common/daemonize.hpp>
12#include <common/error.hpp>
13
99ed9c43 14#include <fcntl.h>
99ed9c43 15#include <stdlib.h>
28ab034a
JG
16#include <sys/wait.h>
17#include <unistd.h>
99ed9c43
MD
18#include <urcu/system.h>
19
28ab034a 20int lttng_daemonize(pid_t *child_ppid, int *completion_flag, int close_fds)
99ed9c43 21{
99ed9c43
MD
22 pid_t pid;
23
24 /* Get parent pid of this process. */
25 *child_ppid = getppid();
26
27 pid = fork();
28 if (pid < 0) {
29 PERROR("fork");
30 goto error;
31 } else if (pid == 0) {
32 int fd;
33 pid_t sid;
44635d77 34 int ret;
99ed9c43
MD
35
36 /* Child */
37
38 /*
39 * Get the newly created parent pid so we can signal
40 * that process when we are ready to operate.
41 */
42 *child_ppid = getppid();
43
44 sid = setsid();
45 if (sid < 0) {
46 PERROR("setsid");
47 goto error;
48 }
49
50 /*
51 * Try to change directory to /. If we can't well at
52 * least notify.
53 */
54 ret = chdir("/");
55 if (ret < 0) {
56 PERROR("chdir");
57 }
58
59 if (close_fds) {
60 fd = open(_PATH_DEVNULL, O_RDWR, 0);
61 if (fd < 0) {
62 PERROR("open %s", _PATH_DEVNULL);
63 /*
64 * Let 0, 1 and 2 open since we can't
65 * bind them to /dev/null.
66 */
67 } else {
68 (void) dup2(fd, STDIN_FILENO);
69 (void) dup2(fd, STDOUT_FILENO);
70 (void) dup2(fd, STDERR_FILENO);
71 if (fd > 2) {
72 ret = close(fd);
73 if (ret < 0) {
74 PERROR("close");
75 }
76 }
77 }
78 }
79 goto end;
80 } else {
81 /* Parent */
82
83 /*
84 * Waiting for child to notify this parent that it can
85 * exit. Note that sleep() is interrupted before the 1
86 * second delay as soon as the signal is received, so it
87 * will not cause visible delay for the user.
88 */
89 while (!CMM_LOAD_SHARED(*completion_flag)) {
90 int status;
91 pid_t ret;
92
93 /*
94 * Check if child exists without blocking. If
95 * so, we have to stop this parent process and
96 * return an error.
97 */
98 ret = waitpid(pid, &status, WNOHANG);
99 if (ret < 0 || (ret != 0 && WIFEXITED(status))) {
100 /* The child exited somehow or was not valid. */
101 goto error;
102 }
103 sleep(1);
104 }
105
106 /*
107 * From this point on, the parent can exit and the child
f3630ec4 108 * is now an operational session daemon ready to serve
99ed9c43
MD
109 * clients and applications.
110 */
111 exit(EXIT_SUCCESS);
112 }
113
114end:
115 return 0;
116
117error:
118 return -1;
119}
This page took 0.089736 seconds and 4 git commands to generate.