xref: /aosp_15_r20/external/libwebsockets/lib/misc/daemonize.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker  * This code is mainly taken from Doug Potter's page
3*1c60b9acSAndroid Build Coastguard Worker  *
4*1c60b9acSAndroid Build Coastguard Worker  * http://www-theorie.physik.unizh.ch/~dpotter/howto/daemonize
5*1c60b9acSAndroid Build Coastguard Worker  *
6*1c60b9acSAndroid Build Coastguard Worker  * I contacted him 2007-04-16 about the license for the original code,
7*1c60b9acSAndroid Build Coastguard Worker  * he replied it is Public Domain.  Use the URL above to get the original
8*1c60b9acSAndroid Build Coastguard Worker  * Public Domain version if you want it.
9*1c60b9acSAndroid Build Coastguard Worker  *
10*1c60b9acSAndroid Build Coastguard Worker  * This version is MIT like the rest of libwebsockets and is
11*1c60b9acSAndroid Build Coastguard Worker  * Copyright (c)2006 - 2013 Andy Green <[email protected]>
12*1c60b9acSAndroid Build Coastguard Worker  *
13*1c60b9acSAndroid Build Coastguard Worker  *
14*1c60b9acSAndroid Build Coastguard Worker  * You're much better advised to use systemd to daemonize stuff without needing
15*1c60b9acSAndroid Build Coastguard Worker  * this kind of support in the app itself.
16*1c60b9acSAndroid Build Coastguard Worker  */
17*1c60b9acSAndroid Build Coastguard Worker 
18*1c60b9acSAndroid Build Coastguard Worker #include <stdlib.h>
19*1c60b9acSAndroid Build Coastguard Worker #include <string.h>
20*1c60b9acSAndroid Build Coastguard Worker #include <stdio.h>
21*1c60b9acSAndroid Build Coastguard Worker #include <signal.h>
22*1c60b9acSAndroid Build Coastguard Worker #include <sys/types.h>
23*1c60b9acSAndroid Build Coastguard Worker #include <sys/stat.h>
24*1c60b9acSAndroid Build Coastguard Worker #include <fcntl.h>
25*1c60b9acSAndroid Build Coastguard Worker #include <limits.h>
26*1c60b9acSAndroid Build Coastguard Worker #include <unistd.h>
27*1c60b9acSAndroid Build Coastguard Worker #include <errno.h>
28*1c60b9acSAndroid Build Coastguard Worker 
29*1c60b9acSAndroid Build Coastguard Worker #include <libwebsockets.h>
30*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
31*1c60b9acSAndroid Build Coastguard Worker 
32*1c60b9acSAndroid Build Coastguard Worker pid_t pid_daemon;
33*1c60b9acSAndroid Build Coastguard Worker static char *lock_path;
34*1c60b9acSAndroid Build Coastguard Worker 
get_daemonize_pid()35*1c60b9acSAndroid Build Coastguard Worker pid_t get_daemonize_pid()
36*1c60b9acSAndroid Build Coastguard Worker {
37*1c60b9acSAndroid Build Coastguard Worker 	return pid_daemon;
38*1c60b9acSAndroid Build Coastguard Worker }
39*1c60b9acSAndroid Build Coastguard Worker 
40*1c60b9acSAndroid Build Coastguard Worker static void
child_handler(int signum)41*1c60b9acSAndroid Build Coastguard Worker child_handler(int signum)
42*1c60b9acSAndroid Build Coastguard Worker {
43*1c60b9acSAndroid Build Coastguard Worker 	int len, sent, fd;
44*1c60b9acSAndroid Build Coastguard Worker 	char sz[20];
45*1c60b9acSAndroid Build Coastguard Worker 
46*1c60b9acSAndroid Build Coastguard Worker 	switch (signum) {
47*1c60b9acSAndroid Build Coastguard Worker 
48*1c60b9acSAndroid Build Coastguard Worker 	case SIGALRM: /* timed out daemonizing */
49*1c60b9acSAndroid Build Coastguard Worker 		exit(0);
50*1c60b9acSAndroid Build Coastguard Worker 		break;
51*1c60b9acSAndroid Build Coastguard Worker 
52*1c60b9acSAndroid Build Coastguard Worker 	case SIGUSR1: /* positive confirmation we daemonized well */
53*1c60b9acSAndroid Build Coastguard Worker 
54*1c60b9acSAndroid Build Coastguard Worker 		if (!lock_path)
55*1c60b9acSAndroid Build Coastguard Worker 			exit(0);
56*1c60b9acSAndroid Build Coastguard Worker 
57*1c60b9acSAndroid Build Coastguard Worker 		/* Create the lock file as the current user */
58*1c60b9acSAndroid Build Coastguard Worker 
59*1c60b9acSAndroid Build Coastguard Worker 		fd = lws_open(lock_path, O_TRUNC | O_RDWR | O_CREAT, 0640);
60*1c60b9acSAndroid Build Coastguard Worker 		if (fd < 0) {
61*1c60b9acSAndroid Build Coastguard Worker 			fprintf(stderr,
62*1c60b9acSAndroid Build Coastguard Worker 			   "unable to create lock file %s, code=%d (%s)\n",
63*1c60b9acSAndroid Build Coastguard Worker 				lock_path, errno, strerror(errno));
64*1c60b9acSAndroid Build Coastguard Worker 			exit(0);
65*1c60b9acSAndroid Build Coastguard Worker 		}
66*1c60b9acSAndroid Build Coastguard Worker 		len = sprintf(sz, "%u", (unsigned int)pid_daemon);
67*1c60b9acSAndroid Build Coastguard Worker 		sent = (int)write(fd, sz, (size_t)len);
68*1c60b9acSAndroid Build Coastguard Worker 		if (sent != len)
69*1c60b9acSAndroid Build Coastguard Worker 			fprintf(stderr,
70*1c60b9acSAndroid Build Coastguard Worker 			  "unable to write pid to lock file %s, code=%d (%s)\n",
71*1c60b9acSAndroid Build Coastguard Worker 					     lock_path, errno, strerror(errno));
72*1c60b9acSAndroid Build Coastguard Worker 
73*1c60b9acSAndroid Build Coastguard Worker 		close(fd);
74*1c60b9acSAndroid Build Coastguard Worker 
75*1c60b9acSAndroid Build Coastguard Worker 		exit(0);
76*1c60b9acSAndroid Build Coastguard Worker 		//!!(sent == len));
77*1c60b9acSAndroid Build Coastguard Worker 
78*1c60b9acSAndroid Build Coastguard Worker 	case SIGCHLD: /* daemonization failed */
79*1c60b9acSAndroid Build Coastguard Worker 		exit(0);
80*1c60b9acSAndroid Build Coastguard Worker 		break;
81*1c60b9acSAndroid Build Coastguard Worker 	}
82*1c60b9acSAndroid Build Coastguard Worker }
83*1c60b9acSAndroid Build Coastguard Worker 
lws_daemon_closing(int sigact)84*1c60b9acSAndroid Build Coastguard Worker static void lws_daemon_closing(int sigact)
85*1c60b9acSAndroid Build Coastguard Worker {
86*1c60b9acSAndroid Build Coastguard Worker 	if (getpid() == pid_daemon)
87*1c60b9acSAndroid Build Coastguard Worker 		if (lock_path) {
88*1c60b9acSAndroid Build Coastguard Worker 			unlink(lock_path);
89*1c60b9acSAndroid Build Coastguard Worker 			lws_free_set_NULL(lock_path);
90*1c60b9acSAndroid Build Coastguard Worker 		}
91*1c60b9acSAndroid Build Coastguard Worker 
92*1c60b9acSAndroid Build Coastguard Worker 	kill(getpid(), SIGKILL);
93*1c60b9acSAndroid Build Coastguard Worker }
94*1c60b9acSAndroid Build Coastguard Worker 
95*1c60b9acSAndroid Build Coastguard Worker /*
96*1c60b9acSAndroid Build Coastguard Worker  * You just need to call this from your main(), when it
97*1c60b9acSAndroid Build Coastguard Worker  * returns you are all set "in the background" decoupled
98*1c60b9acSAndroid Build Coastguard Worker  * from the console you were started from.
99*1c60b9acSAndroid Build Coastguard Worker  *
100*1c60b9acSAndroid Build Coastguard Worker  * The process context you called from has been terminated then.
101*1c60b9acSAndroid Build Coastguard Worker  */
102*1c60b9acSAndroid Build Coastguard Worker 
103*1c60b9acSAndroid Build Coastguard Worker int
lws_daemonize(const char * _lock_path)104*1c60b9acSAndroid Build Coastguard Worker lws_daemonize(const char *_lock_path)
105*1c60b9acSAndroid Build Coastguard Worker {
106*1c60b9acSAndroid Build Coastguard Worker 	struct sigaction act;
107*1c60b9acSAndroid Build Coastguard Worker 	pid_t sid, parent;
108*1c60b9acSAndroid Build Coastguard Worker 
109*1c60b9acSAndroid Build Coastguard Worker 	/* already a daemon */
110*1c60b9acSAndroid Build Coastguard Worker //	if (getppid() == 1)
111*1c60b9acSAndroid Build Coastguard Worker //		return 1;
112*1c60b9acSAndroid Build Coastguard Worker 
113*1c60b9acSAndroid Build Coastguard Worker 	if (_lock_path) {
114*1c60b9acSAndroid Build Coastguard Worker 		int n;
115*1c60b9acSAndroid Build Coastguard Worker 
116*1c60b9acSAndroid Build Coastguard Worker 		int fd = lws_open(_lock_path, O_RDONLY);
117*1c60b9acSAndroid Build Coastguard Worker 		if (fd >= 0) {
118*1c60b9acSAndroid Build Coastguard Worker 			char buf[10];
119*1c60b9acSAndroid Build Coastguard Worker 
120*1c60b9acSAndroid Build Coastguard Worker 			n = (int)read(fd, buf, sizeof(buf));
121*1c60b9acSAndroid Build Coastguard Worker 			close(fd);
122*1c60b9acSAndroid Build Coastguard Worker 			if (n) {
123*1c60b9acSAndroid Build Coastguard Worker 				int ret;
124*1c60b9acSAndroid Build Coastguard Worker 				n = atoi(buf);
125*1c60b9acSAndroid Build Coastguard Worker 				ret = kill(n, 0);
126*1c60b9acSAndroid Build Coastguard Worker 				if (ret >= 0) {
127*1c60b9acSAndroid Build Coastguard Worker 					fprintf(stderr,
128*1c60b9acSAndroid Build Coastguard Worker 					     "Daemon already running pid %d\n",
129*1c60b9acSAndroid Build Coastguard Worker 					     n);
130*1c60b9acSAndroid Build Coastguard Worker 					exit(1);
131*1c60b9acSAndroid Build Coastguard Worker 				}
132*1c60b9acSAndroid Build Coastguard Worker 				fprintf(stderr,
133*1c60b9acSAndroid Build Coastguard Worker 				    "Removing stale lock %s from dead pid %d\n",
134*1c60b9acSAndroid Build Coastguard Worker 							_lock_path, n);
135*1c60b9acSAndroid Build Coastguard Worker 				unlink(lock_path);
136*1c60b9acSAndroid Build Coastguard Worker 			}
137*1c60b9acSAndroid Build Coastguard Worker 		}
138*1c60b9acSAndroid Build Coastguard Worker 
139*1c60b9acSAndroid Build Coastguard Worker 		n = (int)strlen(_lock_path) + 1;
140*1c60b9acSAndroid Build Coastguard Worker 		lock_path = lws_malloc((unsigned int)n, "daemonize lock");
141*1c60b9acSAndroid Build Coastguard Worker 		if (!lock_path) {
142*1c60b9acSAndroid Build Coastguard Worker 			fprintf(stderr, "Out of mem in lws_daemonize\n");
143*1c60b9acSAndroid Build Coastguard Worker 			return 1;
144*1c60b9acSAndroid Build Coastguard Worker 		}
145*1c60b9acSAndroid Build Coastguard Worker 		strcpy(lock_path, _lock_path);
146*1c60b9acSAndroid Build Coastguard Worker 	}
147*1c60b9acSAndroid Build Coastguard Worker 
148*1c60b9acSAndroid Build Coastguard Worker 	/* Trap signals that we expect to receive */
149*1c60b9acSAndroid Build Coastguard Worker 	signal(SIGCHLD, child_handler);	/* died */
150*1c60b9acSAndroid Build Coastguard Worker 	signal(SIGUSR1, child_handler); /* was happy */
151*1c60b9acSAndroid Build Coastguard Worker 	signal(SIGALRM, child_handler); /* timeout daemonizing */
152*1c60b9acSAndroid Build Coastguard Worker 
153*1c60b9acSAndroid Build Coastguard Worker 	/* Fork off the parent process */
154*1c60b9acSAndroid Build Coastguard Worker 	pid_daemon = fork();
155*1c60b9acSAndroid Build Coastguard Worker 	if ((int)pid_daemon < 0) {
156*1c60b9acSAndroid Build Coastguard Worker 		fprintf(stderr, "unable to fork daemon, code=%d (%s)",
157*1c60b9acSAndroid Build Coastguard Worker 		    errno, strerror(errno));
158*1c60b9acSAndroid Build Coastguard Worker 		exit(9);
159*1c60b9acSAndroid Build Coastguard Worker 	}
160*1c60b9acSAndroid Build Coastguard Worker 
161*1c60b9acSAndroid Build Coastguard Worker         /* If we got a good PID, then we can exit the parent process. */
162*1c60b9acSAndroid Build Coastguard Worker 	if (pid_daemon > 0) {
163*1c60b9acSAndroid Build Coastguard Worker 
164*1c60b9acSAndroid Build Coastguard Worker                /*
165*1c60b9acSAndroid Build Coastguard Worker                 * Wait for confirmation signal from the child via
166*1c60b9acSAndroid Build Coastguard Worker                 * SIGCHILD / USR1, or for two seconds to elapse
167*1c60b9acSAndroid Build Coastguard Worker                 * (SIGALRM).  pause() should not return.
168*1c60b9acSAndroid Build Coastguard Worker                 */
169*1c60b9acSAndroid Build Coastguard Worker                alarm(2);
170*1c60b9acSAndroid Build Coastguard Worker 
171*1c60b9acSAndroid Build Coastguard Worker                pause();
172*1c60b9acSAndroid Build Coastguard Worker                /* should not be reachable */
173*1c60b9acSAndroid Build Coastguard Worker                exit(1);
174*1c60b9acSAndroid Build Coastguard Worker        }
175*1c60b9acSAndroid Build Coastguard Worker 
176*1c60b9acSAndroid Build Coastguard Worker 	/* At this point we are executing as the child process */
177*1c60b9acSAndroid Build Coastguard Worker 	parent = getppid();
178*1c60b9acSAndroid Build Coastguard Worker 	pid_daemon = getpid();
179*1c60b9acSAndroid Build Coastguard Worker 
180*1c60b9acSAndroid Build Coastguard Worker 	/* Cancel certain signals */
181*1c60b9acSAndroid Build Coastguard Worker 	signal(SIGCHLD, SIG_DFL); /* A child process dies */
182*1c60b9acSAndroid Build Coastguard Worker 	signal(SIGTSTP, SIG_IGN); /* Various TTY signals */
183*1c60b9acSAndroid Build Coastguard Worker 	signal(SIGTTOU, SIG_IGN);
184*1c60b9acSAndroid Build Coastguard Worker 	signal(SIGTTIN, SIG_IGN);
185*1c60b9acSAndroid Build Coastguard Worker 	signal(SIGHUP, SIG_IGN); /* Ignore hangup signal */
186*1c60b9acSAndroid Build Coastguard Worker 
187*1c60b9acSAndroid Build Coastguard Worker 	/* Change the file mode mask */
188*1c60b9acSAndroid Build Coastguard Worker 	umask(0);
189*1c60b9acSAndroid Build Coastguard Worker 
190*1c60b9acSAndroid Build Coastguard Worker 	/* Create a new SID for the child process */
191*1c60b9acSAndroid Build Coastguard Worker 	sid = setsid();
192*1c60b9acSAndroid Build Coastguard Worker 	if (sid < 0) {
193*1c60b9acSAndroid Build Coastguard Worker 		fprintf(stderr,
194*1c60b9acSAndroid Build Coastguard Worker 			"unable to create a new session, code %d (%s)",
195*1c60b9acSAndroid Build Coastguard Worker 			errno, strerror(errno));
196*1c60b9acSAndroid Build Coastguard Worker 		exit(2);
197*1c60b9acSAndroid Build Coastguard Worker 	}
198*1c60b9acSAndroid Build Coastguard Worker 
199*1c60b9acSAndroid Build Coastguard Worker 	/*
200*1c60b9acSAndroid Build Coastguard Worker 	 * Change the current working directory.  This prevents the current
201*1c60b9acSAndroid Build Coastguard Worker 	 * directory from being locked; hence not being able to remove it.
202*1c60b9acSAndroid Build Coastguard Worker 	 */
203*1c60b9acSAndroid Build Coastguard Worker 	if (chdir("/tmp") < 0) {
204*1c60b9acSAndroid Build Coastguard Worker 		fprintf(stderr,
205*1c60b9acSAndroid Build Coastguard Worker 			"unable to change directory to %s, code %d (%s)",
206*1c60b9acSAndroid Build Coastguard Worker 			"/", errno, strerror(errno));
207*1c60b9acSAndroid Build Coastguard Worker 		exit(3);
208*1c60b9acSAndroid Build Coastguard Worker 	}
209*1c60b9acSAndroid Build Coastguard Worker 
210*1c60b9acSAndroid Build Coastguard Worker 	/* Redirect standard files to /dev/null */
211*1c60b9acSAndroid Build Coastguard Worker 	if (!freopen("/dev/null", "r", stdin))
212*1c60b9acSAndroid Build Coastguard Worker 		fprintf(stderr, "unable to freopen() stdin, code %d (%s)",
213*1c60b9acSAndroid Build Coastguard Worker 						       errno, strerror(errno));
214*1c60b9acSAndroid Build Coastguard Worker 
215*1c60b9acSAndroid Build Coastguard Worker 	if (!freopen("/dev/null", "w", stdout))
216*1c60b9acSAndroid Build Coastguard Worker 		fprintf(stderr, "unable to freopen() stdout, code %d (%s)",
217*1c60b9acSAndroid Build Coastguard Worker 						       errno, strerror(errno));
218*1c60b9acSAndroid Build Coastguard Worker 
219*1c60b9acSAndroid Build Coastguard Worker 	if (!freopen("/dev/null", "w", stderr))
220*1c60b9acSAndroid Build Coastguard Worker 		fprintf(stderr, "unable to freopen() stderr, code %d (%s)",
221*1c60b9acSAndroid Build Coastguard Worker 						       errno, strerror(errno));
222*1c60b9acSAndroid Build Coastguard Worker 
223*1c60b9acSAndroid Build Coastguard Worker 	/* Tell the parent process that we are A-okay */
224*1c60b9acSAndroid Build Coastguard Worker 	kill(parent, SIGUSR1);
225*1c60b9acSAndroid Build Coastguard Worker 
226*1c60b9acSAndroid Build Coastguard Worker 	act.sa_handler = lws_daemon_closing;
227*1c60b9acSAndroid Build Coastguard Worker 	sigemptyset(&act.sa_mask);
228*1c60b9acSAndroid Build Coastguard Worker 	act.sa_flags = 0;
229*1c60b9acSAndroid Build Coastguard Worker 
230*1c60b9acSAndroid Build Coastguard Worker 	sigaction(SIGTERM, &act, NULL);
231*1c60b9acSAndroid Build Coastguard Worker 
232*1c60b9acSAndroid Build Coastguard Worker 	/* return to continue what is now "the daemon" */
233*1c60b9acSAndroid Build Coastguard Worker 
234*1c60b9acSAndroid Build Coastguard Worker 	return 0;
235*1c60b9acSAndroid Build Coastguard Worker }
236*1c60b9acSAndroid Build Coastguard Worker 
237