2 * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
23 #include <sys/types.h>
27 #include <iniparser.h>
29 #include "common/mm_resource_manager_utils.h"
30 #include "daemon/mm_resource_manager_daemon_priv.h"
31 #include "daemon/mm_resource_manager_daemon_conf.h"
32 #include "lib/mm_resource_manager.h"
36 #define PID_FILE "/tmp/.mm-res-mgr.pid"
37 #define PID_MSG_LEN (16)
41 MM_RESOURCE_MANAGER_DAEMON_NOW,
42 MM_RESOURCE_MANAGER_DAEMON_FAIL,
43 MM_RESOURCE_MANAGER_DAEMON_PARENT,
48 static GMainLoop *main_loop;
49 static gboolean restart = FALSE;
53 static gboolean fork_wait(void);
54 static daemonize_result_e daemonize(const char *path);
55 static gboolean init_event(gpointer user_data);
56 static void daemon_loop();
57 static gboolean create_pid_file(void);
58 static gboolean create_ready_file(void);
59 static gboolean create_daemon_setup_file(void);
60 static gboolean remove_pid_file(void);
61 static gboolean remove_ready_file(void);
62 static gboolean remove_daemon_setup_file(void);
63 static int set_signal_handlers();
64 static void terminate_handler(int signum);
65 static void reload_conf_handler(int signum);
66 static void quit_main_loop();
70 static gboolean fork_wait(void)
74 char msg[PID_MSG_LEN] = {'\0',};
76 MM_RM_RETVM_IF(pipe(fds) == -1, FALSE, "Failed to create pipe to get child status");
78 MM_RM_RETVM_IF((pid = fork()) < 0, FALSE, "Daemon fork failed");
81 /* Read in a string from the pipe */
82 MM_RM_RETVM_IF(read(fds[0], msg, sizeof(msg)) < 0,
83 FALSE, "Failed to create pipe to get child status");
88 /* Parent process closes up output side of pipe */
89 if (!strcmp(msg, MSG_DONE)) {
90 MM_RM_DEBUG("Successfully daemonized");
93 MM_RM_ERROR("Daemonizing failed after fork");
96 } else if (pid == 0) {
97 /* Child process closes up input side of pipe */
98 notify_fd[0] = fds[0];
99 notify_fd[1] = fds[1];
105 static daemonize_result_e daemonize(const char *path)
107 MM_RM_RETVM_IF(fork_wait() == FALSE, MM_RESOURCE_MANAGER_DAEMON_FAIL,
108 "Daemon fork&wait to set waiting until child process of fork actually completes failed");
111 MM_RM_RETVM_IF(setsid() < 0, MM_RESOURCE_MANAGER_DAEMON_FAIL,
112 "Daemon cannot set session id");
113 MM_RM_RETVM_IF(chdir(path ? path : "/") < 0,
114 MM_RESOURCE_MANAGER_DAEMON_FAIL, "Daemon cannot chdir");
117 !freopen("/dev/null", "r", stdin) ||
118 !freopen("/dev/null", "w", stdout) ||
119 !freopen("/dev/null", "w", stderr),
120 MM_RESOURCE_MANAGER_DAEMON_FAIL,
121 "Daemon cannot redirect std streams");
123 MM_RM_DEBUG("Daemonize succeeded");
125 return MM_RESOURCE_MANAGER_DAEMON_NOW;
128 static gboolean init_event(gpointer user_data)
130 MM_RM_DEBUG("main loop = %p", main_loop);
131 if (!_mmrm_dmn_init())
132 g_main_loop_quit(main_loop);
134 return G_SOURCE_REMOVE;
137 static void daemon_loop()
144 MM_RM_RETM_IF(!mm_resource_manager_reload_conf(),
145 "Daemon cannot reload conf");
147 main_loop = g_main_loop_new(NULL, FALSE);
148 MM_RM_RETM_IF(main_loop == NULL, "Daemon cannot create main loop");
150 if ((id = g_timeout_add(100, init_event, NULL)) == 0) {
151 MM_RM_ERROR("Init event cannot be added to main loop");
155 MM_RM_INFO("Daemon loop [%p] is ran", main_loop);
156 g_main_loop_run(main_loop);
157 MM_RM_INFO("Daemon loop end");
162 g_main_loop_unref(main_loop);
165 MM_RM_RETM_IF(g_source_remove(id) == FALSE, "Failed to remove %d", id);
169 static gboolean create_pid_file(void)
173 char pid_buf[PID_MSG_LEN] = {'\0',};
175 fd = open(PID_FILE, O_WRONLY | O_CREAT, (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
176 MM_RM_RETVM_IF(fd < 0, FALSE, "PID file cannot be created (%d)", errno);
178 lock.l_type = F_WRLCK;
180 lock.l_whence = SEEK_SET;
183 if (fcntl(fd, F_SETLK, &lock) < 0) {
184 if (errno != EACCES && errno != EAGAIN)
185 MM_RM_ERROR("Fail to lock pidfile [%d]", errno);
187 MM_RM_ERROR("process is already running");
192 if (ftruncate(fd, 0) < 0) {
193 MM_RM_ERROR("Fail to truncate pidfile [%d]", errno);
197 memset(pid_buf, 0, sizeof(pid_buf));
198 snprintf(pid_buf, sizeof(pid_buf), "%u", getpid());
200 if (write(fd, pid_buf, strlen(pid_buf)) != (int)strlen(pid_buf)) {
201 MM_RM_ERROR("Fail to write pid to pidfile [%d]", errno);
207 MM_RM_INFO("PID file (%s) is created", PID_FILE);
215 static gboolean create_ready_file(void)
219 if ((fd = creat(MM_RESOURCE_MANAGER_READY, 0644)) != -1) {
220 MM_RM_INFO("ready file(%s) file was created", MM_RESOURCE_MANAGER_READY);
223 MM_RM_ERROR("cannot create ready file(%s), errno(%d)", MM_RESOURCE_MANAGER_READY, errno);
230 static gboolean create_daemon_setup_file(void)
232 return create_pid_file() && create_ready_file();
235 static gboolean remove_pid_file(void)
237 if (unlink(PID_FILE) != 0) {
238 LOGE("%s : unlink failed, errno(%d)", PID_FILE, errno);
245 static gboolean remove_ready_file(void)
247 if (unlink(MM_RESOURCE_MANAGER_READY) != 0) {
248 LOGE("%s : unlink failed, errno(%d)", MM_RESOURCE_MANAGER_READY, errno);
255 static gboolean remove_daemon_setup_file(void)
257 return remove_pid_file() && remove_ready_file();
260 static int set_signal_handlers()
262 struct sigaction sa_term;
263 struct sigaction sa_reload_conf;
264 struct sigaction sa_ignore;
266 sa_term.sa_handler = terminate_handler;
267 sigemptyset(&sa_term.sa_mask);
268 sa_term.sa_flags = SA_RESETHAND;
270 sa_reload_conf.sa_handler = reload_conf_handler;
271 sigemptyset(&sa_reload_conf.sa_mask);
272 sa_reload_conf.sa_flags = 0;
274 sa_ignore.sa_handler = SIG_IGN;
275 sigemptyset(&sa_ignore.sa_mask);
276 sa_ignore.sa_flags = 0;
278 return sigaction(SIGTERM, &sa_term, NULL) != -1 &&
279 sigaction(SIGINT, &sa_ignore, NULL) != -1 &&
280 sigaction(SIGQUIT, &sa_ignore, NULL) != -1 &&
281 sigaction(SIGHUP, &sa_reload_conf, NULL) != -1;
284 static void terminate_handler(int signum)
286 MM_RM_DEBUG("SIGTERM is received");
290 static void reload_conf_handler(int signum)
292 MM_RM_DEBUG("SIGHUP is received");
297 static void quit_main_loop()
300 _mmrm_dmn_status_callback(MM_RESOURCE_MANAGER_STATUS_DISCONNECTED);
301 g_main_loop_quit(main_loop);
305 int main(int argc, char *argv[])
307 switch (daemonize(NULL)) {
309 case MM_RESOURCE_MANAGER_DAEMON_NOW:
310 MM_RM_RETVM_IF(!set_signal_handlers(), EXIT_FAILURE,
311 "Daemon cannot set signal handlers");
312 MM_RM_RETVM_IF(!create_daemon_setup_file(), EXIT_FAILURE,
313 "Daemon cannot create setup file");
317 MM_RM_RETVM_IF(!remove_daemon_setup_file(), EXIT_FAILURE,
318 "Daemon cannot remove setup file");
320 case MM_RESOURCE_MANAGER_DAEMON_PARENT:
323 case MM_RESOURCE_MANAGER_DAEMON_FAIL: