Merge singleton fix related changes into swap_protocol
[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 #ifndef LOCALTEST
46 #include <attr/xattr.h>         // for fsetxattr
47 #endif
48 #include "daemon.h"
49 #include "da_protocol.h"
50 #include "sys_stat.h"
51 #include "buffer.h"
52 #include "debug.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         .portfile = NULL,
66         .host_server_socket = -1,
67         .target_server_socket = -1,
68         .target_count = 0,
69         .config_flag = 0,
70         .app_launch_timerfd = -1,
71         .sampling_thread = -1,
72         .replay_thread = -1,
73         .transfer_thread = -1,
74         .buf_fd = -1,
75         .efd = -1,
76
77         .host = {
78                 .control_socket = -1,
79                 .data_socket = -1,
80                 .data_socket_mutex = PTHREAD_MUTEX_INITIALIZER
81         },
82
83         .target = {
84                 {0L, },
85         },
86
87         .appPath = {0, }
88
89         };
90 // =============================================================================
91 // util functions
92 // =============================================================================
93
94 static void writeToPortfile(int code)
95 {
96         if(unlikely(manager.portfile == 0))
97                 return;
98
99         fprintf(manager.portfile, "%d", code);
100 }
101
102 // =============================================================================
103 // atexit functions
104 // =============================================================================
105
106 void _close_server_socket(void)
107 {
108         LOGI("close_server_socket\n");
109         // close server socket
110         if(manager.host_server_socket != -1)
111                 close(manager.host_server_socket);
112         if(manager.target_server_socket != -1)
113                 close(manager.target_server_socket);
114 }
115
116 static void _unlink_file(void)
117 {
118         LOGI("unlink files start\n");
119         unlink(PORTFILE);
120         unlink(SINGLETON_LOCKFILE);
121         LOGI("unlink files done\n");
122 }
123
124 void unlink_portfile(void)
125 {
126         unlink(PORTFILE);
127 }
128
129 // =============================================================================
130 // making sockets
131 // =============================================================================
132
133 // return 0 for normal case
134 static int makeTargetServerSocket()
135 {
136         struct sockaddr_un serverAddrUn;
137
138         if(manager.target_server_socket != -1)
139                 return -1;      // should be never happend
140
141         // remove existed unix domain socket file
142         unlink(UDS_NAME);
143
144         if ((manager.target_server_socket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
145         {
146                 LOGE("Target server socket creation failed\n");
147                 return -1;
148         }
149
150 #ifndef LOCALTEST
151         // set smack attribute for certification
152         fsetxattr(manager.target_server_socket, "security.SMACK64IPIN", "*", 1, 0);
153         fsetxattr(manager.target_server_socket, "security.SMACK64IPOUT", "*", 1, 0);
154 #endif /* LOCALTEST */
155
156         bzero(&serverAddrUn, sizeof(serverAddrUn));
157         serverAddrUn.sun_family = AF_UNIX;
158         sprintf(serverAddrUn.sun_path, "%s", UDS_NAME);
159
160         if (-1 == bind(manager.target_server_socket, (struct sockaddr*) &serverAddrUn,
161                                         sizeof(serverAddrUn)))
162         {
163                 LOGE("Target server socket binding failed\n");
164                 return -1;
165         }
166
167         chmod(serverAddrUn.sun_path, 0777);
168
169         if (-1 == listen(manager.target_server_socket, 5))
170         {
171                 LOGE("Target server socket listening failed\n");
172                 return -1;
173         }
174
175         LOGI("Created TargetSock %d\n", manager.target_server_socket);
176         return 0;
177 }
178
179 // return port number for normal case
180 // return negative value for error case
181 static int makeHostServerSocket()
182 {
183         struct sockaddr_in serverAddrIn;
184         int opt = 1;
185         int port;
186
187         if(manager.host_server_socket != -1)
188                 return -1;      // should be never happened
189
190         if ((manager.host_server_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
191         {
192                 LOGE("Host server socket creation failed\n");
193                 return -1;
194         }
195
196         setsockopt(manager.host_server_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
197         memset(&serverAddrIn, 0, sizeof(serverAddrIn));
198         serverAddrIn.sin_family = AF_INET;
199         serverAddrIn.sin_addr.s_addr = htonl(INADDR_ANY);
200
201         // bind address to server socket
202         for(port = INIT_PORT; port < LIMIT_PORT; port++)
203         {
204                 serverAddrIn.sin_port = htons(port);
205                 if (0 == bind(manager.host_server_socket,
206                                         (struct sockaddr*) &serverAddrIn, sizeof(serverAddrIn)))
207                         break;
208         }
209
210         if(port == LIMIT_PORT)
211         {
212                 LOGE("Host server socket binding failed\n");
213                 return -1;
214         }
215
216         // enter listen state from client
217         if (-1 == listen(manager.host_server_socket, 5))
218         {
219                 LOGE("Host server socket listening failed\n");
220                 return -1;
221         }
222
223         LOGI("Created HostSock %d\n", manager.host_server_socket);
224         return port;
225 }
226
227 // =============================================================================
228 // initializing / finalizing functions
229 // =============================================================================
230
231 static bool ensure_singleton(const char *lockfile)
232 {
233         if (access(lockfile, F_OK) == 0)        /* File exists */
234                 return false;
235
236         int lockfd = open(lockfile, O_WRONLY | O_CREAT, 0600);
237         if (lockfd < 0) {
238                 writeToPortfile(ERR_LOCKFILE_CREATE_FAILED);
239                 LOGE("singleton lock file creation failed");
240                 return false;
241         }
242         /* To prevent race condition, also check for lock availiability. */
243         bool locked = flock(lockfd, LOCK_EX | LOCK_NB) == 0;
244
245         if (!locked) {
246                 writeToPortfile(ERR_ALREADY_RUNNING);
247                 LOGE("another instance of daemon is already running");
248         }
249         close(lockfd);
250         return locked;
251 }
252 static void inititialize_manager_targets(__da_manager * mng)
253 {
254         int index;
255         __da_target_info target_init_value = {
256                 .pid = -1,
257                 .socket = -1,
258                 .event_fd = -1,
259                 .recv_thread = -1,
260                 .initial_log = 0,
261                 .allocmem = 0,
262                 .starttime = 0
263         };
264
265         for (index = 0; index < MAX_TARGET_COUNT; index++)
266                 mng->target[index] = target_init_value;
267
268         manager.target_count = 0;
269 }
270
271 static bool initialize_pthread_sigmask()
272 {
273         sigset_t newsigmask;
274
275         sigemptyset(&newsigmask);
276         sigaddset(&newsigmask, SIGALRM);
277         sigaddset(&newsigmask, SIGUSR1);
278         if (pthread_sigmask(SIG_BLOCK, &newsigmask, NULL) != 0) {
279                 writeToPortfile(ERR_SIGNAL_MASK_SETTING_FAILED);
280                 return false;
281         }
282         return true;
283 }
284
285 static bool initialize_host_server_socket()
286 {
287         int port = makeHostServerSocket();
288
289         if (port < 0) {
290                 writeToPortfile(ERR_HOST_SERVER_SOCKET_CREATE_FAILED);
291                 return false;
292         }
293         writeToPortfile(port);
294         return true;
295 }
296
297 // return 0 for normal case
298 static int initializeManager()
299 {
300         if (init_buf() != 0) {
301                 LOGE("Cannot init buffer\n");
302                 return -1;
303         }
304
305         atexit(_close_server_socket);
306         if(initialize_system_info() < 0)
307         {
308                 writeToPortfile(ERR_INITIALIZE_SYSTEM_INFO_FAILED);
309                 return -1;
310         }
311
312         // make server socket
313         if(makeTargetServerSocket() != 0)
314         {
315                 writeToPortfile(ERR_TARGET_SERVER_SOCKET_CREATE_FAILED);
316                 return -1;
317         }
318
319         if (!initialize_host_server_socket())
320           return -1;
321
322         LOGI("SUCCESS to write port\n");
323
324         inititialize_manager_targets(&manager);
325         if (!initialize_pthread_sigmask())
326           return -1;
327         // initialize sendMutex
328         pthread_mutex_init(&(manager.host.data_socket_mutex), NULL);
329
330         return 0;
331 }
332
333 static int finalizeManager()
334 {
335         LOGI("Finalize daemon\n");
336 #ifndef LOCALTEST
337         LOGI("finalize system info\n");
338         finalize_system_info();
339 #endif
340
341         // close host client socket
342         if(manager.host.control_socket != -1){
343                 LOGI("close host control socket (%d)\n", manager.host.control_socket);
344                 close(manager.host.control_socket);
345         }
346         if(manager.host.data_socket != -1){
347                 LOGI("close host data socket (%d)\n", manager.host.data_socket);
348                 close(manager.host.data_socket);
349         }
350
351         LOGI("exit buf\n");
352         exit_buf();
353
354         LOGI("return\n");
355         return 0;
356 }
357
358 // main function
359 int main()
360 {
361         int result;
362         if (!ensure_singleton(SINGLETON_LOCKFILE))
363                 return 1;
364
365         initialize_log();
366
367         LOGI("da_started\n");
368         atexit(_unlink_file);
369
370         manager.portfile = fopen(PORTFILE, "w");
371         if (manager.portfile == NULL) {
372                 LOGE("cannot create portfile");
373                 return 1;
374         }
375         //for terminal exit
376         signal(SIGHUP, SIG_IGN);
377         chdir("/");
378
379         //new session reader
380         setsid();
381
382         // initialize manager
383         result = initializeManager();
384         fclose(manager.portfile);
385         if(result == 0)
386         {
387                 //daemon work
388                 //FIX ME remove samplingThread it is only for debug
389                 //samplingThread(NULL);
390                 daemonLoop();
391                 LOGI("daemon loop finished\n");
392                 stop_all();
393                 finalizeManager();
394                 LOGI("main finished\n");
395                 return 0;
396         }
397         else
398         {
399                 return 1;
400         }
401 }