Tizen 2.0 Release
[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 "ss_device_plugin.h"
26 #include "ss_log.h"
27 #include "ss_launch.h"
28 #include "include/ss_data.h"
29
30 #define PMON_PERMANENT_DIR      "/tmp/permanent"
31
32 static int pmon_fd = -1;
33
34 static int replace_char(int size, char *t)
35 {
36         while (size > 0) {
37                 if (*t == 0)
38                         *t = ' ';
39                 size--;
40                 t++;
41         }
42         return 0;
43 }
44
45 static char *pmon_get_permanent_pname(int pid)
46 {
47         int fd;
48         char buf[PATH_MAX];
49         struct stat st;
50         char *cmdline = NULL;
51
52         snprintf(buf, sizeof(buf), "%s/%d", PMON_PERMANENT_DIR, pid);
53         fd = open(buf, O_RDONLY);
54         if (fd == -1) {
55                 PRT_TRACE_ERR("file open error");
56                 return NULL;
57         }
58
59         if (fstat(fd, &st) < 0) {
60                 PRT_TRACE_ERR("fstat error");
61                 close(fd);
62                 return NULL;
63         }
64
65         PRT_TRACE("size = %d", (int)st.st_size);
66
67         cmdline = malloc(st.st_size + 1);
68         if (cmdline == NULL) {
69                 PRT_TRACE_ERR("Not enough memory");
70                 close(fd);
71                 return NULL;
72         }
73         memset(cmdline, 0, st.st_size + 1);
74
75         read(fd, cmdline, st.st_size);
76         /* TODO - must change more smarter */
77         replace_char(st.st_size - 1, cmdline);
78         close(fd);
79
80         return cmdline;
81 }
82
83 static void print_pmon_state(unsigned int dead_pid)
84 {
85         PRT_TRACE("[Process MON] %d killed", dead_pid);
86 }
87
88 static int pmon_process(int pid, void *ad)
89 {
90         char *cmdline;
91         int new_pid;
92         char old_file[PATH_MAX];
93         int fd;
94         int r;
95
96         if (sysconf_is_vip(pid)) {
97                 PRT_TRACE_ERR("=======================================");
98                 PRT_TRACE_ERR("[Process MON] VIP process dead.");
99                 PRT_TRACE_ERR("=======================================");
100         }
101         /* If there is NOT a .hibernation_start file, run following codes 
102          * On hibernation processing, just ignore relaunching */
103         else if (access("/tmp/.hibernation_start", R_OK) != 0) {
104                 cmdline = pmon_get_permanent_pname(pid);
105                 if (cmdline != NULL) {
106                         PRT_TRACE("[Process MON] %s relaunch", cmdline);
107                         new_pid = ss_launch_evenif_exist(cmdline, "");
108                         free(cmdline);
109                         if (new_pid > 0) {
110                                 /* TODO - set oom */
111                                 char buf[PATH_MAX];
112                                 char filepath[PATH_MAX];
113                                 int cnt;
114
115                                 if (access(PMON_PERMANENT_DIR, R_OK) < 0) {
116                                         PRT_TRACE("no predefined matrix dir = %s, so created", PMON_PERMANENT_DIR);
117                                         r = mkdir(PMON_PERMANENT_DIR, 0777);
118                                         if(r < 0) {
119                                                 PRT_TRACE("Make Directory is failed");
120                                                 return -1;
121                                         }
122                                 }
123
124                                 snprintf(filepath, sizeof(filepath), "%s/%d", PMON_PERMANENT_DIR, pid);
125                                 fd = open(filepath, O_RDONLY);
126                                 if (fd == -1) {
127                                         PRT_TRACE("Failed to open");
128                                         return -1;
129                                 }
130
131                                 cnt = read(fd, buf, PATH_MAX);
132                                 close(fd);
133
134                                 if (cnt <= 0) {
135                                         PRT_TRACE("Failed to read");
136                                         return -1;
137                                 }
138
139                                 snprintf(filepath, sizeof(filepath), "%s/%d", PMON_PERMANENT_DIR, new_pid);
140
141                                 fd = open(filepath, O_CREAT | O_WRONLY, 0644);
142                                 if (fd == -1) {
143                                         PRT_TRACE("Failed to open");
144                                         return -1;
145                                 }
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 (0 > plugin_intf->OEM_sys_set_process_monitor_mp_pnp(new_pid)) {
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                                 snprintf(buf, sizeof(buf), "/proc/%d/oom_adj",
165                                          new_pid);
166                                 fp = fopen(buf, "w");
167                                 if (fp == NULL)
168                                         return -1;
169                                 fprintf(fp, "%d", (-17));
170                                 fclose(fp);
171
172                                 snprintf(old_file, sizeof(old_file), "%s/%d",
173                                          PMON_PERMANENT_DIR, pid);
174                                 unlink(old_file);
175                         } else { 
176                                 PRT_TRACE_ERR("[Process MON] failed relaunching");
177                         }
178                 }
179         }
180         return 0;
181 }
182 /*
183 static unsigned int pmon_read(int fd)
184 {
185         unsigned int pid;
186         read(fd, &pid, sizeof(pid));
187         return pid;
188 }
189 */
190
191 static int pmon_cb(void *data, Ecore_Fd_Handler * fd_handler)
192 {
193         int fd;
194         struct ss_main_data *ad = (struct ss_main_data *)data;
195         int dead_pid;
196
197         if (!ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)) {
198                 PRT_TRACE_ERR
199                     ("ecore_main_fd_handler_active_get error , return\n");
200                 return 1;
201         }
202
203         fd = ecore_main_fd_handler_fd_get(fd_handler);
204
205         if (fd < 0) {
206                 PRT_TRACE_ERR("ecore_main_fd_handler_fd_get error , return");
207                 return 1;
208         }
209         if ((read(fd, &dead_pid, sizeof(dead_pid))) < 0) {
210                 PRT_TRACE_ERR("Reading DEAD_PID failed, Return");
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         char pmon_dev_node[PATH_MAX];
223
224         if (0 > plugin_intf->OEM_sys_get_process_monitor_node(pmon_dev_node)) {
225                 PRT_TRACE_ERR("ss_pmon_init get dev node path failed");
226                 return -1;
227         }
228
229         pmon_fd = open(pmon_dev_node, O_RDONLY);
230         if (pmon_fd < 0) {
231                 PRT_TRACE_ERR("ss_pmon_init fd open failed");
232                 return -1;
233         }
234         ecore_main_fd_handler_add(pmon_fd, ECORE_FD_READ, pmon_cb, ad, NULL,
235                                   NULL);
236         return 0;
237 }