[FIX] empty string in sprintf
[platform/core/system/swap-manager.git] / daemon / main.c
1 /*
2  *  DA manager
3  *
4  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  *
8  * Jaewon Lim <jaewon81.lim@samsung.com>
9  * Woojin Jung <woojin2.jung@samsung.com>
10  * Juyoung Kim <j0.kim@samsung.com>
11  * Cherepanov Vitaliy <v.cherepanov@samsung.com>
12  * Nikita Kalyazin    <n.kalyazin@samsung.com>
13  *
14  * Licensed under the Apache License, Version 2.0 (the "License");
15  * you may not use this file except in compliance with the License.
16  * You may obtain a copy of the License at
17  *
18  * http://www.apache.org/licenses/LICENSE-2.0
19  *
20  * Unless required by applicable law or agreed to in writing, software
21  * distributed under the License is distributed on an "AS IS" BASIS,
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23  * See the License for the specific language governing permissions and
24  * limitations under the License.
25  *
26  * Contributors:
27  * - S-Core Co., Ltd
28  * - Samsung RnD Institute Russia
29  *
30  */
31
32 #include <stdio.h>                      // for fopen, fprintf
33 #include <stdlib.h>                     // for atexit
34 #include <sys/types.h>          // for open
35 #include <sys/file.h>
36 #include <sys/stat.h>           // for open
37 #include <sys/socket.h>         // for socket
38 #include <sys/un.h>                     // for sockaddr_un
39 #include <arpa/inet.h>          // for sockaddr_in, socklen_t
40
41 #include <signal.h>                     // for signal
42 #include <unistd.h>                     // for unlink
43 #include <fcntl.h>                      // for open, fcntl
44 #include <stdbool.h>
45 #include <attr/xattr.h>         // for fsetxattr
46 #include "daemon.h"
47 #include "da_protocol.h"
48 #include "sys_stat.h"
49 #include "buffer.h"
50 #include "debug.h"
51 #include "utils.h"
52
53 #define SINGLETON_LOCKFILE                      "/tmp/da_manager.lock"
54 #define PORTFILE                                        "/tmp/port.da"
55 #define UDS_NAME                                        "/tmp/da.socket"
56
57 #define INIT_PORT                               8001
58 #define LIMIT_PORT                              8100
59
60
61 // initialize global variable
62 __da_manager manager =
63 {
64         .host_server_socket = -1,
65         .target_server_socket = -1,
66         .target_count = 0,
67         .apps_to_run = 0,
68         .config_flag = 0,
69         .app_launch_timerfd = -1,
70         .connect_timeout_timerfd = -1,
71         .sampling_thread = -1,
72         .replay_thread = -1,
73         .transfer_thread = -1,
74         .buf_fd = -1,
75         .user_ev_fd = -1,
76         .efd = -1,
77
78         .host = {
79                 .control_socket = -1,
80                 .data_socket = -1,
81                 .data_socket_mutex = PTHREAD_MUTEX_INITIALIZER
82         },
83
84         .target = {
85                 {0L, },
86         },
87         .fd = {
88                 .brightness = -1,
89                 .voltage = -1,
90                 .procmeminfo = -1,
91                 .video = NULL,
92                 .procstat = NULL,
93                 .networkstat = NULL,
94                 .diskstats = NULL
95         },
96         .appPath = {0, }
97
98         };
99 // =============================================================================
100 // util functions
101 // =============================================================================
102
103 static void write_int(FILE *fp, int code)
104 {
105         fprintf(fp, "%d", code);
106 }
107
108 // =============================================================================
109 // atexit functions
110 // =============================================================================
111
112 static void _close_server_socket(void)
113 {
114         LOGI("close_server_socket\n");
115         // close server socket
116         if(manager.host_server_socket != -1)
117                 close(manager.host_server_socket);
118         if(manager.target_server_socket != -1)
119                 close(manager.target_server_socket);
120 }
121
122 static void _unlink_files(void)
123 {
124         LOGI("unlink files start\n");
125         unlink(PORTFILE);
126         unlink(SINGLETON_LOCKFILE);
127         LOGI("unlink files done\n");
128 }
129
130 void unlink_portfile(void)
131 {
132         unlink(PORTFILE);
133 }
134
135 // =============================================================================
136 // making sockets
137 // =============================================================================
138
139 // return 0 for normal case
140 static int makeTargetServerSocket()
141 {
142         struct sockaddr_un serverAddrUn;
143
144         if(manager.target_server_socket != -1)
145                 return -1;      // should be never happend
146
147         // remove existed unix domain socket file
148         unlink(UDS_NAME);
149
150         if ((manager.target_server_socket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
151         {
152                 LOGE("Target server socket creation failed\n");
153                 return -1;
154         }
155
156         fd_setup_smack_attributes(manager.target_server_socket);
157
158         memset(&serverAddrUn, '\0', sizeof(serverAddrUn));
159         serverAddrUn.sun_family = AF_UNIX;
160         sprintf(serverAddrUn.sun_path, "%s", UDS_NAME);
161
162         if (-1 == bind(manager.target_server_socket, (struct sockaddr*) &serverAddrUn,
163                                         sizeof(serverAddrUn)))
164         {
165                 LOGE("Target server socket binding failed\n");
166                 return -1;
167         }
168
169         if(chmod(serverAddrUn.sun_path, 0777) < 0)
170         {
171                 LOGE("Failed to change mode for socket file : errno(%d)\n", errno);
172         }
173
174
175         if (-1 == listen(manager.target_server_socket, 5))
176         {
177                 LOGE("Target server socket listening failed\n");
178                 return -1;
179         }
180
181         LOGI("Created TargetSock %d\n", manager.target_server_socket);
182         return 0;
183 }
184
185 // return port number for normal case
186 // return negative value for error case
187 static int makeHostServerSocket()
188 {
189         struct sockaddr_in serverAddrIn;
190         int opt = 1;
191         int port;
192
193         if(manager.host_server_socket != -1)
194                 return -1;      // should be never happened
195
196         if ((manager.host_server_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
197         {
198                 LOGE("Host server socket creation failed\n");
199                 return -1;
200         }
201
202         if(setsockopt(manager.host_server_socket,
203            SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
204         {
205                 LOGE("Failed to set socket option : errno(%d)\n", errno);
206         }
207
208         memset(&serverAddrIn, 0, sizeof(serverAddrIn));
209         serverAddrIn.sin_family = AF_INET;
210         serverAddrIn.sin_addr.s_addr = htonl(INADDR_ANY);
211
212         // bind address to server socket
213         for(port = INIT_PORT; port < LIMIT_PORT; port++)
214         {
215                 serverAddrIn.sin_port = htons(port);
216                 if (0 == bind(manager.host_server_socket,
217                                         (struct sockaddr*) &serverAddrIn, sizeof(serverAddrIn)))
218                         break;
219         }
220
221         if(port == LIMIT_PORT)
222         {
223                 LOGE("Host server socket binding failed\n");
224                 return -1;
225         }
226
227         // enter listen state from client
228         if (-1 == listen(manager.host_server_socket, 5))
229         {
230                 LOGE("Host server socket listening failed\n");
231                 return -1;
232         }
233
234         LOGI("Created HostSock %d\n", manager.host_server_socket);
235         return port;
236 }
237
238 // =============================================================================
239 // initializing / finalizing functions
240 // =============================================================================
241
242 static bool ensure_singleton(const char *lockfile)
243 {
244         if (access(lockfile, F_OK) == 0)        /* File exists */
245                 return false;
246
247         int lockfd = open(lockfile, O_WRONLY | O_CREAT, 0600);
248         if (lockfd < 0) {
249                 LOGE("singleton lock file creation failed");
250                 return false;
251         }
252         /* To prevent race condition, also check for lock availiability. */
253         bool locked = flock(lockfd, LOCK_EX | LOCK_NB) == 0;
254
255         if (!locked) {
256                 LOGE("another instance of daemon is already running");
257         }
258         close(lockfd);
259         return locked;
260 }
261
262 static void inititialize_manager_targets(__da_manager * mng)
263 {
264         int index;
265         __da_target_info target_init_value = {
266                 .pid = -1,
267                 .socket = -1,
268                 .event_fd = -1,
269                 .recv_thread = -1,
270                 .initial_log = 0,
271                 .allocmem = 0
272         };
273
274         for (index = 0; index < MAX_TARGET_COUNT; index++)
275                 mng->target[index] = target_init_value;
276
277         manager.target_count = 0;
278 }
279
280 static bool initialize_pthread_sigmask()
281 {
282         sigset_t newsigmask;
283
284         sigemptyset(&newsigmask);
285         sigaddset(&newsigmask, SIGALRM);
286         sigaddset(&newsigmask, SIGUSR1);
287         return pthread_sigmask(SIG_BLOCK, &newsigmask, NULL) == 0;
288 }
289
290 // return 0 for normal case
291 static int initializeManager(FILE *portfile)
292 {
293         if (init_buf() != 0) {
294                 LOGE("Cannot init buffer\n");
295                 return -1;
296         }
297
298         if (initialize_system_info() < 0) {
299                 write_int(portfile, ERR_INITIALIZE_SYSTEM_INFO_FAILED);
300                 return -1;
301         }
302         // make server socket
303         if (makeTargetServerSocket() != 0) {
304                 write_int(portfile, ERR_TARGET_SERVER_SOCKET_CREATE_FAILED);
305                 return -1;
306         }
307         if (!initialize_pthread_sigmask()) {
308                 write_int(portfile, ERR_SIGNAL_MASK_SETTING_FAILED);
309                 return -1;
310         }
311
312         int port = makeHostServerSocket();
313         if (port < 0) {
314                 write_int(portfile, ERR_HOST_SERVER_SOCKET_CREATE_FAILED);
315                 return -1;
316         } else {
317                 write_int(portfile, port);
318         }
319
320         LOGI("SUCCESS to write port\n");
321
322         inititialize_manager_targets(&manager);
323
324         // initialize sendMutex
325         pthread_mutex_init(&(manager.host.data_socket_mutex), NULL);
326
327         return 0;
328 }
329
330
331 static int finalizeManager()
332 {
333         LOGI("Finalize daemon\n");
334         LOGI("finalize system info\n");
335         finalize_system_info();
336
337         // close host client socket
338         if(manager.host.control_socket != -1){
339                 LOGI("close host control socket (%d)\n", manager.host.control_socket);
340                 close(manager.host.control_socket);
341         }
342         if(manager.host.data_socket != -1){
343                 LOGI("close host data socket (%d)\n", manager.host.data_socket);
344                 close(manager.host.data_socket);
345         }
346
347         LOGI("return\n");
348         return 0;
349 }
350
351 static void remove_buf_modules(void)
352 {
353         LOGI("rmmod buffer start\n");
354         if (system("cd /opt/swap/sdk && ./stop.sh")) {
355                 LOGW("Cannot remove swap modules\n");
356         }
357         LOGI("rmmod buffer done\n");
358 }
359
360 static void terminate(int sig)
361 {
362         LOGI("terminate! sig = %d\n", sig);
363         if (!stop_all_in_process()) {
364                 // we are up there if signal accept and stop_all func was not
365                 // called yet.
366
367                 // so we need stop_all firstly (if profiling was
368                 // not started it will be dummy call) and release other sources
369                 stop_all_no_lock();
370                 _unlink_files();
371                 _close_server_socket();
372                 exit_buf();
373                 remove_buf_modules();
374                 if (sig != 0) {
375                         LOGW("Terminating due signal %s\n", strsignal(sig));
376                         signal(sig, SIG_DFL);
377                         raise(sig);
378                 }
379                 stop_all_done();
380         } else {
381                 // we are there if stop_all function was called by some reasons
382
383                 // if stop_all called we cannot call remove_buf_modules and
384                 // other funcs because of threads are not stopped yet
385                 LOGW("Stop in progress\n");
386                 if (sig != 0) {
387                         LOGW("ignore signal %s\n", strsignal(sig));
388                         signal(sig, SIG_IGN);
389                 }
390         }
391 }
392
393 static void terminate0()
394 {
395         terminate(0);
396 }
397
398
399 static void setup_signals()
400 {
401         struct sigaction sigact = {
402                 .sa_handler = terminate,
403                 .sa_flags = 0
404         };
405         sigemptyset(&sigact.sa_mask);
406         sigaction(SIGTERM, &sigact, 0);
407         sigaction(SIGINT, &sigact, 0);
408
409         signal(SIGHUP, SIG_IGN);
410         signal(SIGPIPE,SIG_IGN);
411 }
412
413 // main function
414 int main()
415 {
416         if (!ensure_singleton(SINGLETON_LOCKFILE))
417                 return 1;
418
419         initialize_log();
420
421         LOGI("da_started\n");
422         atexit(terminate0);
423
424
425         //for terminal exit
426         setup_signals();
427         daemon(0, 1);
428         LOGI("--- daemonized (pid %d) ---\n", getpid());
429
430         FILE *portfile = fopen(PORTFILE, "w");
431         if (!portfile) {
432                 LOGE("cannot create portfile");
433                 return 1;
434         }
435
436         int err = initializeManager(portfile);
437         fclose(portfile);
438         if (err)
439                 return 1;
440
441         //init all file descriptors
442         init_system_file_descriptors();
443         //daemon work
444         //FIX ME remove samplingThread it is only for debug
445         //samplingThread(NULL);
446         daemonLoop();
447         LOGI("daemon loop finished\n");
448         stop_all();
449         finalizeManager();
450
451         close_system_file_descriptors();
452
453         LOGI("main finished\n");
454         return 0;
455 }