c1c6278fe747abe17a11d4aa86a8b843a2327b87
[platform/core/multimedia/libmm-sound.git] / focus_server / mm_sound_focus_server.c
1 /*
2  * libmm-sound
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Seungbae Shin <seungbae.shin@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/wait.h>
26 #include <unistd.h>
27 #include <getopt.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30
31 #include <mm_debug.h>
32
33 #include <fcntl.h>
34 #include <semaphore.h>
35
36 #ifdef USE_LWIPC
37 #include <lwipc.h>
38 #endif
39
40 #include "../include/mm_sound_common.h"
41 #include "../include/mm_sound_utils.h"
42 #include "include/mm_sound_mgr_focus.h"
43 #include "include/mm_sound_mgr_focus_dbus.h"
44 #include "include/mm_sound_mgr_focus_socket.h"
45
46 #define USE_SYSTEM_SERVER_PROCESS_MONITORING
47
48 typedef struct {
49         int startserver;
50         int printlist;
51         int testmode;
52 } server_arg;
53
54 static int _get_option(int argc, char **argv, server_arg *arg);
55 static int _usage(int argc, char **argv);
56
57 static GMainLoop *g_mainloop;
58
59 static void _mainloop_run()
60 {
61         g_mainloop = g_main_loop_new(NULL, TRUE);
62         if (g_mainloop == NULL)
63                 debug_error("g_main_loop_new() failed");
64
65         g_main_loop_run(g_mainloop);
66 }
67
68 static int _get_option(int argc, char **argv, server_arg *arg)
69 {
70         int c;
71         static struct option long_options[] = {
72                 {"start", 0, 0, 'S'},
73                 {"help", 0, 0, 'H'},
74                 {"testmode", 0, 0, 'T'},
75                 {0, 0, 0, 0}
76         };
77         memset(arg, 0, sizeof(server_arg));
78
79         arg->testmode = 0;
80
81         while (1) {
82                 int opt_idx = 0;
83
84                 c = getopt_long (argc, argv, "SFLHRUP:Tiurd", long_options, &opt_idx);
85                 if (c == -1)
86                         break;
87                 switch (c) {
88                 case 'S': /* Start daemon */
89                         arg->startserver = 1;
90                         break;
91                 case 'T': /* Test mode */
92                         arg->testmode = 1;
93                         break;
94                 case 'H': /* help msg */
95                 default:
96                         return _usage(argc, argv);
97                 }
98         }
99         if (argc == 1)
100                 return _usage(argc, argv);
101         return 0;
102 }
103
104 static int _usage(int argc, char **argv)
105 {
106         fprintf(stderr, "Usage: %s [Options]\n", argv[0]);
107         fprintf(stderr, "\t%-20s: start focus server.\n", "--start,-S");
108         fprintf(stderr, "\t%-20s: help message.\n", "--help,-H");
109
110         return 1;
111 }
112
113 static void _generate_ready_file(const char *path)
114 {
115         int fd = -1;
116
117         if (path == NULL) {
118                 debug_error("path is NULL");
119                 return;
120         }
121
122         if ((fd = creat(path, 0644)) != -1) {
123                 debug_warning("ready file(%s) file was created", path);
124                 close(fd);
125         } else {
126                 debug_error("cannot create ready file(%s), errno(%d)", path, errno);
127         }
128 }
129
130 static int g_socket_fd = -1;
131 static struct sigaction _int_old_action;
132 static struct sigaction _abrt_old_action;
133 static struct sigaction _segv_old_action;
134 static struct sigaction _term_old_action;
135 static struct sigaction _sys_old_action;
136 static struct sigaction _xcpu_old_action;
137
138 static void _signal_handler(int signo)
139 {
140         debug_warning("ENTER, sig.num(%d)", signo);
141
142         MMSoundMgrFocusDbusFini();
143         MMSoundMgrFocusFini();
144         MMSoundMgrFocusSocketFini(g_socket_fd);
145
146 #ifdef USE_GCOV
147         mm_sound_gcov_flush();
148 #endif
149
150         /* signal block -------------- */
151         sigset_t old_mask, all_mask;
152         sigfillset(&all_mask);
153         sigprocmask(SIG_BLOCK, &all_mask, &old_mask);
154
155         sigprocmask(SIG_SETMASK, &old_mask, NULL);
156         /* signal unblock ------------ */
157
158         switch (signo) {
159         case SIGINT:
160                 sigaction(SIGINT, &_int_old_action, NULL);
161                 raise(signo);
162                 break;
163         case SIGABRT:
164                 sigaction(SIGABRT, &_abrt_old_action, NULL);
165                 raise(signo);
166                 break;
167         case SIGSEGV:
168                 sigaction(SIGSEGV, &_segv_old_action, NULL);
169                 raise(signo);
170                 break;
171         case SIGTERM:
172                 sigaction(SIGTERM, &_term_old_action, NULL);
173                 raise(signo);
174                 break;
175         case SIGSYS:
176                 sigaction(SIGSYS, &_sys_old_action, NULL);
177                 raise(signo);
178                 break;
179         case SIGXCPU:
180                 sigaction(SIGXCPU, &_xcpu_old_action, NULL);
181                 raise(signo);
182                 break;
183         default:
184                 break;
185         }
186         debug_warning("LEAVE");
187 }
188
189 static void _signal_initialize(void)
190 {
191         struct sigaction _action;
192         _action.sa_handler = _signal_handler;
193         _action.sa_flags = SA_NOCLDSTOP;
194
195         sigemptyset(&_action.sa_mask);
196
197         sigaction(SIGINT, &_action, &_int_old_action);
198         sigaction(SIGABRT, &_action, &_abrt_old_action);
199         sigaction(SIGSEGV, &_action, &_segv_old_action);
200         sigaction(SIGTERM, &_action, &_term_old_action);
201         sigaction(SIGSYS, &_action, &_sys_old_action);
202         sigaction(SIGXCPU, &_action, &_xcpu_old_action);
203
204 }
205
206 static void _signal_finalize(void)
207 {
208         sigaction(SIGINT, &_int_old_action, NULL);
209         sigaction(SIGABRT, &_abrt_old_action, NULL);
210         sigaction(SIGSEGV, &_segv_old_action, NULL);
211         sigaction(SIGTERM, &_term_old_action, NULL);
212         sigaction(SIGSYS, &_sys_old_action, NULL);
213         sigaction(SIGXCPU, &_xcpu_old_action, NULL);
214 }
215
216 int main(int argc, char **argv)
217 {
218         server_arg serveropt;
219 #if !defined(USE_SYSTEM_SERVER_PROCESS_MONITORING)
220         int pid;
221 #endif
222         int socket_fd = -1;
223
224         if (_get_option(argc, argv, &serveropt))
225                 return 1;
226
227         debug_warning("focus_server [%d] init ", getpid());
228
229         _signal_initialize();
230
231         /* Daemon process create */
232         if (!serveropt.testmode && serveropt.startserver) {
233 #if !defined(USE_SYSTEM_SERVER_PROCESS_MONITORING)
234                 daemon(0, 0); //chdir to ("/"), and close stdio
235 #endif
236         }
237
238         /* focus Server Starts!!!*/
239         debug_warning("focus_server [%d] start ", getpid());
240
241         signal(SIGPIPE, SIG_IGN); //ignore SIGPIPE
242
243 #if !defined(USE_SYSTEM_SERVER_PROCESS_MONITORING)
244         while (1) {
245                 if ((pid = fork()) < 0) {
246                         fprintf(stderr, "Sub Fork Error\n");
247                         return 2;
248                 } else if (pid == 0) {
249                         break;
250                 } else if (pid > 0) {
251                         wait(&ret);
252                         fprintf(stderr, "Killed by signal [%05X]\n", ret);
253                         fprintf(stderr, "Daemon is run againg\n");
254                 }
255         }
256 #endif
257
258 #ifdef USE_GCOV
259         mm_sound_gcov_set_prefix();
260 #endif
261
262         if (serveropt.startserver) {
263                 /* Change the file mode mask */
264                 umask(0);
265
266                 if (MMSoundMgrFocusSocketInit(&socket_fd)) {
267                         debug_error("focus_server [%d] terminating, due to the error of socket init.", getpid());
268                         return 0;
269                 }
270                 if (MMSoundMgrFocusSocketReadyToWork(socket_fd)) {
271                         debug_error("focus_server [%d] terminating, due to the error of thread init.", getpid());
272                         return 0;
273                 }
274                 MMSoundMgrFocusDbusInit();
275                 MMSoundMgrFocusInit();
276                 g_socket_fd = socket_fd;
277         }
278
279         debug_warning("focus_server [%d] initialization complete...now, start running!!", getpid());
280
281         if (serveropt.startserver) {
282                 unlink(PA_READY); // remove pa_ready file after focus-server init.
283
284                 /* FIXME : This code is moved from sound_server temporally for TV migration
285                                         As other modules which has dependancy on this file is cleared,
286                                         this code will be removed */
287                 /* broadcast if we're ready */
288 #ifdef USE_LWIPC
289                 if (LwipcEventDone(SOUND_SERVER_READY) < 0)
290                         debug_error("cannot create SOUND_SERVER_READY(sound_server_ready)");
291                 else
292                         debug_warning("SOUND_SERVER_READY(%s) event was created", SOUND_SERVER_READY);
293 #else
294                 _generate_ready_file(SOUND_SERVER_READY);
295 #endif
296                 _generate_ready_file(FOCUS_SERVER_READY);
297
298                 _mainloop_run();
299         }
300
301         debug_warning("focus_server [%d] terminating ", getpid());
302
303         if (serveropt.startserver) {
304                 MMSoundMgrFocusDbusFini();
305                 MMSoundMgrFocusFini();
306                 MMSoundMgrFocusSocketFini(socket_fd);
307         }
308
309         _signal_finalize();
310
311         debug_warning("focus_server [%d] exit ----------------- END ", getpid());
312
313         return 0;
314 }