[REFACTOR] encapsulate target struct (part 1)
[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 <errno.h>
45 #include <stdbool.h>
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 #include "smack.h"
53
54 #define SINGLETON_LOCKFILE                      "/tmp/da_manager.lock"
55 #define PORTFILE                                        "/tmp/port.da"
56 #define UDS_NAME                                        "/tmp/da.socket"
57
58 #define INIT_PORT                               8001
59 #define LIMIT_PORT                              8100
60
61
62 // initialize global variable
63 __da_manager manager =
64 {
65         .host_server_socket = -1,
66         .target_server_socket = -1,
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         .fd = {
85                 .brightness = -1,
86                 .voltage = -1,
87                 .procmeminfo = -1,
88                 .video = NULL,
89                 .procstat = NULL,
90                 .networkstat = NULL,
91                 .diskstats = NULL
92         },
93         .appPath = {0, }
94
95         };
96 // =============================================================================
97 // util functions
98 // =============================================================================
99
100 static void write_int(FILE *fp, int code)
101 {
102         fprintf(fp, "%d", code);
103 }
104
105 // =============================================================================
106 // atexit functions
107 // =============================================================================
108
109 static void _close_server_socket(void)
110 {
111         LOGI("close_server_socket\n");
112         // close server socket
113         if(manager.host_server_socket != -1)
114                 close(manager.host_server_socket);
115         if(manager.target_server_socket != -1)
116                 close(manager.target_server_socket);
117 }
118
119 static void _unlink_files(void)
120 {
121         LOGI("unlink files start\n");
122         unlink(PORTFILE);
123         unlink(SINGLETON_LOCKFILE);
124         LOGI("unlink files done\n");
125 }
126
127 void unlink_portfile(void)
128 {
129         unlink(PORTFILE);
130 }
131
132 // =============================================================================
133 // making sockets
134 // =============================================================================
135
136 // return 0 for normal case
137 static int makeTargetServerSocket()
138 {
139         struct sockaddr_un serverAddrUn;
140
141         if(manager.target_server_socket != -1)
142                 return -1;      // should be never happend
143
144         // remove existed unix domain socket file
145         unlink(UDS_NAME);
146
147         manager.target_server_socket = socket(AF_UNIX,
148                                               SOCK_STREAM | SOCK_CLOEXEC, 0);
149         if (manager.target_server_socket < 0)
150         {
151                 LOGE("Target server socket creation failed\n");
152                 return -1;
153         }
154
155         fd_setup_attributes(manager.target_server_socket);
156
157         memset(&serverAddrUn, '\0', sizeof(serverAddrUn));
158         serverAddrUn.sun_family = AF_UNIX;
159         sprintf(serverAddrUn.sun_path, "%s", UDS_NAME);
160
161         if (-1 == bind(manager.target_server_socket, (struct sockaddr*) &serverAddrUn,
162                                         sizeof(serverAddrUn)))
163         {
164                 LOGE("Target server socket binding failed\n");
165                 return -1;
166         }
167
168         if(chmod(serverAddrUn.sun_path, 0777) < 0)
169         {
170                 LOGE("Failed to change mode for socket file : errno(%d)\n", errno);
171         }
172
173
174         if (-1 == listen(manager.target_server_socket, 5))
175         {
176                 LOGE("Target server socket listening failed\n");
177                 return -1;
178         }
179
180         LOGI("Created TargetSock %d\n", manager.target_server_socket);
181         return 0;
182 }
183
184 // return port number for normal case
185 // return negative value for error case
186 static int makeHostServerSocket()
187 {
188         struct sockaddr_in serverAddrIn;
189         int opt = 1;
190         int port;
191
192         if(manager.host_server_socket != -1)
193                 return -1;      // should be never happened
194
195         manager.host_server_socket = socket(PF_INET,
196                                             SOCK_STREAM | SOCK_CLOEXEC,
197                                             IPPROTO_TCP);
198         if (manager.host_server_socket < 0)
199         {
200                 LOGE("Host server socket creation failed\n");
201                 return -1;
202         }
203
204         if(setsockopt(manager.host_server_socket,
205            SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
206         {
207                 LOGE("Failed to set socket option : errno(%d)\n", errno);
208         }
209
210         memset(&serverAddrIn, 0, sizeof(serverAddrIn));
211         serverAddrIn.sin_family = AF_INET;
212         serverAddrIn.sin_addr.s_addr = htonl(INADDR_ANY);
213
214         // bind address to server socket
215         for(port = INIT_PORT; port < LIMIT_PORT; port++)
216         {
217                 serverAddrIn.sin_port = htons(port);
218                 if (0 == bind(manager.host_server_socket,
219                                         (struct sockaddr*) &serverAddrIn, sizeof(serverAddrIn)))
220                         break;
221         }
222
223         if(port == LIMIT_PORT)
224         {
225                 LOGE("Host server socket binding failed\n");
226                 return -1;
227         }
228
229         // enter listen state from client
230         if (-1 == listen(manager.host_server_socket, 5))
231         {
232                 LOGE("Host server socket listening failed\n");
233                 return -1;
234         }
235
236         LOGI("Created HostSock %d\n", manager.host_server_socket);
237         return port;
238 }
239
240 // =============================================================================
241 // initializing / finalizing functions
242 // =============================================================================
243
244 static bool ensure_singleton(const char *lockfile)
245 {
246         if (access(lockfile, F_OK) == 0)        /* File exists */
247                 return false;
248
249         int lockfd = open(lockfile, O_WRONLY | O_CREAT, 0600);
250         if (lockfd < 0) {
251                 LOGE("singleton lock file creation failed");
252                 return false;
253         }
254         /* To prevent race condition, also check for lock availiability. */
255         bool locked = flock(lockfd, LOCK_EX | LOCK_NB) == 0;
256
257         if (!locked) {
258                 LOGE("another instance of daemon is already running");
259         }
260         close(lockfd);
261         return locked;
262 }
263
264 static void inititialize_manager_targets(void)
265 {
266         target_cnt_set(0);
267 }
268
269 static bool initialize_pthread_sigmask()
270 {
271         sigset_t newsigmask;
272
273         sigemptyset(&newsigmask);
274         sigaddset(&newsigmask, SIGALRM);
275         sigaddset(&newsigmask, SIGUSR1);
276         return pthread_sigmask(SIG_BLOCK, &newsigmask, NULL) == 0;
277 }
278
279 // return 0 for normal case
280 static int initializeManager(FILE *portfile)
281 {
282         if (init_buf() != 0) {
283                 LOGE("Cannot init buffer\n");
284                 return -1;
285         }
286
287         if (initialize_system_info() < 0) {
288                 write_int(portfile, ERR_INITIALIZE_SYSTEM_INFO_FAILED);
289                 return -1;
290         }
291         // make server socket
292         if (makeTargetServerSocket() != 0) {
293                 write_int(portfile, ERR_TARGET_SERVER_SOCKET_CREATE_FAILED);
294                 return -1;
295         }
296         if (!initialize_pthread_sigmask()) {
297                 write_int(portfile, ERR_SIGNAL_MASK_SETTING_FAILED);
298                 return -1;
299         }
300
301         int port = makeHostServerSocket();
302         if (port < 0) {
303                 write_int(portfile, ERR_HOST_SERVER_SOCKET_CREATE_FAILED);
304                 return -1;
305         } else {
306                 write_int(portfile, port);
307         }
308
309         LOGI("SUCCESS to write port\n");
310
311         inititialize_manager_targets();
312
313         // initialize sendMutex
314         pthread_mutex_init(&(manager.host.data_socket_mutex), NULL);
315
316         return 0;
317 }
318
319
320 static int finalizeManager()
321 {
322         LOGI("Finalize daemon\n");
323         LOGI("finalize system info\n");
324         finalize_system_info();
325
326         // close host client socket
327         if(manager.host.control_socket != -1){
328                 LOGI("close host control socket (%d)\n", manager.host.control_socket);
329                 close(manager.host.control_socket);
330         }
331         if(manager.host.data_socket != -1){
332                 LOGI("close host data socket (%d)\n", manager.host.data_socket);
333                 close(manager.host.data_socket);
334         }
335
336         LOGI("return\n");
337         return 0;
338 }
339
340 static void remove_buf_modules(void)
341 {
342         LOGI("rmmod buffer start\n");
343         if (system("cd /opt/swap/sdk && ./stop.sh")) {
344                 LOGW("Cannot remove swap modules\n");
345         }
346         LOGI("rmmod buffer done\n");
347 }
348
349 static void terminate(int sig)
350 {
351         LOGI("terminate! sig = %d\n", sig);
352         if (!stop_all_in_process()) {
353                 // we are up there if signal accept and stop_all func was not
354                 // called yet.
355
356                 // so we need stop_all firstly (if profiling was
357                 // not started it will be dummy call) and release other sources
358                 stop_all_no_lock();
359                 _unlink_files();
360                 _close_server_socket();
361                 exit_buf();
362                 remove_buf_modules();
363                 if (sig != 0) {
364                         LOGW("Terminating due signal %s\n", strsignal(sig));
365                         signal(sig, SIG_DFL);
366                         raise(sig);
367                 }
368                 stop_all_done();
369         } else {
370                 // we are there if stop_all function was called by some reasons
371
372                 // if stop_all called we cannot call remove_buf_modules and
373                 // other funcs because of threads are not stopped yet
374                 LOGW("Stop in progress\n");
375                 if (sig != 0) {
376                         LOGW("ignore signal %s\n", strsignal(sig));
377                         signal(sig, SIG_IGN);
378                 }
379         }
380 }
381
382 static void terminate0()
383 {
384         terminate(0);
385 }
386
387
388 static void setup_signals()
389 {
390         struct sigaction sigact = {
391                 .sa_handler = terminate,
392                 .sa_flags = 0
393         };
394         sigemptyset(&sigact.sa_mask);
395         sigaction(SIGTERM, &sigact, 0);
396         sigaction(SIGINT, &sigact, 0);
397
398         signal(SIGHUP, SIG_IGN);
399         signal(SIGPIPE,SIG_IGN);
400 }
401
402 // main function
403 int main()
404 {
405         if (!ensure_singleton(SINGLETON_LOCKFILE))
406                 return 1;
407
408         initialize_log();
409
410         LOGI("da_started\n");
411         atexit(terminate0);
412
413
414         //for terminal exit
415         setup_signals();
416         daemon(0, 1);
417         LOGI("--- daemonized (pid %d) ---\n", getpid());
418
419         FILE *portfile = fopen(PORTFILE, "w");
420         if (!portfile) {
421                 LOGE("cannot create portfile");
422                 return 1;
423         }
424
425         int err = initializeManager(portfile);
426         fclose(portfile);
427         if (err)
428                 return 1;
429
430         //init all file descriptors
431         init_system_file_descriptors();
432         //daemon work
433         //FIX ME remove samplingThread it is only for debug
434         //samplingThread(NULL);
435         daemonLoop();
436         LOGI("daemon loop finished\n");
437         stop_all();
438         finalizeManager();
439
440         close_system_file_descriptors();
441
442         //DO NOT USE THIS FUNCTION FOR RELEASE IT IS TOO SLOW
443 #ifdef MALLOC_DEBUG_LEVEL
444         msg_swap_free_all_data(&prof_session.user_space_inst);
445 #endif
446
447         LOGI("main finished\n");
448         print_malloc_list(NULL, 0);
449         return 0;
450 }