42ef9e1cbd42d206e12620ffa2924c4bde863b47
[framework/system/system-server.git] / ss_pmon_handler.c
1 /*
2  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17
18 #include <sysman.h>
19 #include <fcntl.h>
20 #include <assert.h>
21 #include <limits.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24
25 #include "device-node.h"
26 #include "ss_log.h"
27 #include "ss_launch.h"
28 #include "include/ss_data.h"
29 #include "ss_common.h"
30
31 #define PMON_PERMANENT_DIR      "/tmp/permanent"
32
33 static Ecore_Fd_Handler *pmon_efd = NULL;
34
35 static int __pmon_start(struct ss_main_data *ad);
36 static int __pmon_stop(int fd);
37 static int replace_char(int size, char *t)
38 {
39         while (size > 0) {
40                 if (*t == 0)
41                         *t = ' ';
42                 size--;
43                 t++;
44         }
45         return 0;
46 }
47
48 static char *pmon_get_permanent_pname(int pid)
49 {
50         int fd;
51         char buf[PATH_MAX];
52         struct stat st;
53         char *cmdline = NULL;
54
55         snprintf(buf, sizeof(buf), "%s/%d", PMON_PERMANENT_DIR, pid);
56         fd = open(buf, O_RDONLY);
57         if (fd == -1) {
58                 PRT_TRACE_ERR("file open error");
59                 return NULL;
60         }
61
62         if (fstat(fd, &st) < 0) {
63                 PRT_TRACE_ERR("fstat error");
64                 close(fd);
65                 return NULL;
66         }
67         PRT_TRACE("size = %d", (int)st.st_size);
68
69         cmdline = malloc(st.st_size + 1);
70         if (cmdline == NULL) {
71                 PRT_TRACE_ERR("Not enough memory");
72                 close(fd);
73                 return NULL;
74         }
75         memset(cmdline, 0, st.st_size + 1);
76
77         read(fd, cmdline, st.st_size);
78         /* TODO - must change more smarter */
79         replace_char(st.st_size - 1, cmdline);
80         close(fd);
81
82         return cmdline;
83 }
84
85 static void print_pmon_state(unsigned int dead_pid)
86 {
87         PRT_TRACE("[Process MON] %d killed", dead_pid);
88 }
89
90 static int pmon_process(int pid, void *ad)
91 {
92         char *cmdline;
93         int new_pid;
94         char old_file[PATH_MAX];
95         int fd;
96         int r;
97
98         if (sysconf_is_vip(pid)) {
99                 PRT_TRACE_ERR("=======================================");
100                 PRT_TRACE_ERR("[Process MON] VIP process dead.");
101                 PRT_TRACE_ERR("=======================================");
102         }
103         /* If there is NOT a .hibernation_start file, run following codes 
104          * On hibernation processing, just ignore relaunching */
105         else if (access("/tmp/.hibernation_start", R_OK) != 0) {
106                 cmdline = pmon_get_permanent_pname(pid);
107                 if (cmdline != NULL) {
108                         PRT_TRACE("[Process MON] %s relaunch", cmdline);
109                         new_pid = ss_launch_evenif_exist(cmdline, "");
110                         free(cmdline);
111                         if (new_pid > 0) {
112                                 /* TODO - set oom */
113                                 char buf[PATH_MAX];
114                                 char filepath[PATH_MAX];
115                                 int cnt;
116
117                                 if (access(PMON_PERMANENT_DIR, R_OK) < 0) {
118                                         PRT_TRACE("no predefined matrix dir = %s, so created", PMON_PERMANENT_DIR);
119                                         r = mkdir(PMON_PERMANENT_DIR, 0777);
120                                         if(r < 0) {
121                                                 PRT_TRACE("Make Directory is failed");
122                                                 return -1;
123                                         }
124                                 }
125
126                                 snprintf(filepath, sizeof(filepath), "%s/%d", PMON_PERMANENT_DIR, pid);
127                                 fd = open(filepath, O_RDONLY);
128                                 if (fd == -1) {
129                                         PRT_TRACE("Failed to open");
130                                         return -1;
131                                 }
132                                 cnt = read(fd, buf, PATH_MAX);
133                                 close(fd);
134
135                                 if (cnt <= 0) {
136                                         PRT_TRACE("Failed to read");
137                                         return -1;
138                                 }
139
140                                 snprintf(filepath, sizeof(filepath), "%s/%d", PMON_PERMANENT_DIR, new_pid);
141
142                                 fd = open(filepath, O_CREAT | O_WRONLY, 0644);
143                                 if (fd == -1) {
144                                         PRT_TRACE("Failed to open");
145                                         return -1;
146                                 }
147                                 if (write(fd, buf, cnt) == -1) {
148                                         PRT_TRACE("Failed to write");
149                                         close(fd);
150                                         return -1;
151                                 }
152                                 close(fd);
153
154                                 if ( device_set_property(DEVICE_TYPE_PROCESS, PROP_PROCESS_MP_PNP, new_pid) < 0) {
155                                         PRT_TRACE_ERR("Write new pid failed");
156                                 }
157                                 PRT_TRACE("[Process MON] %d ", new_pid);
158
159                                 FILE *fp;
160
161                                 PRT_TRACE
162                                     ("[Process MON] OOMADJ_SET : pid %d, new_oomadj %d",
163                                      new_pid, (-17));
164                                 
165                                 fp = open_proc_oom_adj_file(new_pid, "w");
166                                 if (fp == NULL)
167                                         return -1;
168                                 fprintf(fp, "%d", (-17));
169                                 fclose(fp);
170
171                                 snprintf(old_file, sizeof(old_file), "%s/%d",
172                                          PMON_PERMANENT_DIR, pid);
173                                 unlink(old_file);
174                         } else { 
175                                 PRT_TRACE_ERR("[Process MON] failed relaunching");
176                         }
177                 }
178         }
179         return 0;
180 }
181 /*
182 static unsigned int pmon_read(int fd)
183 {
184         unsigned int pid;
185         read(fd, &pid, sizeof(pid));
186         return pid;
187 }
188 */
189
190 static int pmon_cb(void *data, Ecore_Fd_Handler * fd_handler)
191 {
192         int fd;
193         struct ss_main_data *ad = (struct ss_main_data *)data;
194         int dead_pid;
195         if (!ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)) {
196                 PRT_TRACE_ERR
197                     ("ecore_main_fd_handler_active_get error , return\n");
198                 return -1;
199         }
200
201         fd = ecore_main_fd_handler_fd_get(fd_handler);
202
203         if (fd < 0) {
204                 PRT_TRACE_ERR("ecore_main_fd_handler_fd_get error , return");
205                 return -1;
206         }
207         if (read(fd, &dead_pid, sizeof(dead_pid)) < 0) {
208                 __pmon_stop(fd);
209                 PRT_TRACE_ERR("Reading DEAD_PID failed, restart ecore fd");
210                 __pmon_start(ad);
211                 return -1;
212         }
213                 
214         print_pmon_state(dead_pid);
215         pmon_process(dead_pid, ad);
216
217         return 1;
218 }
219
220 int ss_pmon_init(struct ss_main_data *ad)
221 {
222         int ret = -1;
223         if (pmon_efd) {
224                 ecore_main_fd_handler_del(pmon_efd);
225                 pmon_efd = NULL;
226         }
227         if (__pmon_start(ad) == -1) {
228                 PRT_TRACE_ERR("fail pmon control fd init");
229                 return -1;
230         }
231         return 0;
232 }
233
234 static int __pmon_start(struct ss_main_data *ad)
235 {
236         int pmon_fd = -1;
237         char pmon_dev_node[PATH_MAX];
238
239         if (device_get_property(DEVICE_TYPE_PROCESS, PROP_PROCESS_NODE, pmon_dev_node) < 0) {
240                 PRT_TRACE_ERR("ss_pmon_init get dev node path failed");
241                 return -1;
242         }
243
244         pmon_fd = open(pmon_dev_node, O_RDONLY);
245         if (pmon_fd < 0) {
246                 PRT_TRACE_ERR("ss_pmon_init fd open failed");
247                 return -1;
248         }
249         pmon_efd = ecore_main_fd_handler_add(pmon_fd, ECORE_FD_READ, pmon_cb, ad, NULL, NULL);
250         if (!pmon_efd) {
251                 PRT_TRACE_ERR("error ecore_main_fd_handler_add");
252                 return -1;
253         }
254         return 0;
255 }
256 static int __pmon_stop(int fd)
257 {
258         if (pmon_efd) {
259                 ecore_main_fd_handler_del(pmon_efd);
260                 pmon_efd = NULL;
261         }
262         if (fd >=0) {
263                 close(fd);
264                 fd = -1;
265         }
266         return 0;
267 }