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