cdb21228ca24b6d64341b2e94c45d51c73385825
[framework/system/system-server.git] / ss_pmon_handler.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
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 #include "ss_log.h"
17 #include "ss_launch.h"
18
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <fcntl.h>
22 #include <assert.h>
23 #include <limits.h>
24
25 #define PMON_DEV_NODE "/dev/pmon"
26 #define PMON_PERMANENT_DIR "/tmp/permanent"
27
28 static int pmon_fd = -1;
29
30 static int replace_char(int size, char *t)
31 {
32         while (size > 0) {
33                 if (*t == 0)
34                         *t = ' ';
35                 size--;
36                 t++;
37         }
38         return 0;
39 }
40
41 #define PERNAMENT_DIR   "/tmp/permanent"
42
43 static char *pmon_get_permanent_pname(int pid)
44 {
45         int fd;
46         char buf[PATH_MAX];
47         struct stat st;
48         char *cmdline = NULL;
49
50         snprintf(buf, sizeof(buf), "%s/%d", PERNAMENT_DIR, pid);
51         fd = open(buf, O_RDONLY);
52         if (fd == -1) {
53                 PRT_TRACE_ERR("file open error");
54                 return NULL;
55         }
56
57         if (fstat(fd, &st) < 0) {
58                 PRT_TRACE_ERR("fstat error");
59                 return NULL;
60         }
61
62         PRT_TRACE("size = %d", (int)st.st_size);
63
64         cmdline = malloc(st.st_size + 1);
65         if (cmdline == NULL) {
66                 PRT_TRACE_ERR("Not enough memory");
67                 return NULL;
68         }
69         memset(cmdline, 0, st.st_size + 1);
70
71         read(fd, cmdline, st.st_size);
72         /* TODO - must change more smarter */
73         replace_char(st.st_size - 1, cmdline);
74         close(fd);
75
76         return cmdline;
77 }
78
79 static void print_pmon_state(unsigned int dead_pid)
80 {
81         PRT_TRACE("[Process MON] %d killed", dead_pid);
82 }
83
84 static int pmon_process(unsigned int pid, void *ad)
85 {
86         char *cmdline;
87         int new_pid;
88         char old_file[PATH_MAX];
89         int fd;
90
91         if (sysconf_is_vip(pid)) {
92                 PRT_TRACE_ERR("=======================================");
93                 PRT_TRACE_ERR("[Process MON] VIP process dead.");
94                 PRT_TRACE_ERR("=======================================");
95         }
96         /* If there is NOT a .hibernation_start file, run following codes 
97          * On hibernation processing, just ignore relaunching */
98         else if (access("/tmp/.hibernation_start", R_OK) != 0) {
99                 cmdline = pmon_get_permanent_pname(pid);
100                 if (cmdline != NULL) {
101                         PRT_TRACE("[Process MON] %s relaunch", cmdline);
102                         new_pid = ss_launch_evenif_exist(cmdline, "");
103                         free(cmdline);
104                         if (new_pid > 0) {
105                                 /* TODO - set oom */
106                                 char buf[PATH_MAX];
107                                 char filepath[PATH_MAX];
108                                 size_t cnt;
109
110                                 if (access("/tmp/permanent", R_OK) < 0) {
111                                         PRT_TRACE
112                                             ("no predefined matrix dir = /tmp/permanent, so created");
113                                         mkdir("/tmp/permanent", 0777);
114                                 }
115
116                                 snprintf(filepath, sizeof(filepath),
117                                          "/tmp/permanent/%d", pid);
118                                 fd = open(filepath, O_RDONLY);
119                                 if (fd == -1) {
120                                         PRT_TRACE("Failed to open");
121                                         return -1;
122                                 }
123
124                                 cnt = read(fd, buf, PATH_MAX);
125                                 close(fd);
126
127                                 if (cnt <= 0) {
128                                         PRT_TRACE("Failed to read");
129                                         return -1;
130                                 }
131
132                                 snprintf(filepath, sizeof(filepath), "%s/%d",
133                                          "/tmp/permanent", new_pid);
134
135                                 fd = open(filepath, O_CREAT | O_WRONLY, 0644);
136                                 if (fd == -1) {
137                                         PRT_TRACE("Failed to open");
138                                         return -1;
139                                 }
140
141                                 if (write(fd, buf, cnt) == -1) {
142                                         PRT_TRACE("Failed to write");
143                                         close(fd);
144                                         return -1;
145                                 }
146                                 close(fd);
147
148                                 fd = open("/sys/class/pmon/mp_pnp", O_WRONLY);
149
150                                 if (fd == -1) {
151                                         PRT_TRACE("Failed to open");
152                                         return -1;
153                                 }
154
155                                 write(fd, &new_pid, sizeof(int));
156
157                                 close(fd);
158                                 PRT_TRACE("[Process MON] %d ", new_pid);
159
160                                 FILE *fp;
161
162                                 PRT_TRACE
163                                     ("[Process MON] OOMADJ_SET : pid %d, new_oomadj %d",
164                                      new_pid, (-17));
165                                 snprintf(buf, sizeof(buf), "/proc/%d/oom_adj",
166                                          new_pid);
167                                 fp = fopen(buf, "w");
168                                 if (fp == NULL)
169                                         return -1;
170                                 fprintf(fp, "%d", (-17));
171                                 fclose(fp);
172
173                                 snprintf(old_file, sizeof(old_file), "%s/%d",
174                                          PMON_PERMANENT_DIR, pid);
175                                 unlink(old_file);
176                         } else { 
177                                 PRT_TRACE_ERR("[Process MON] failed relaunching");
178                         }
179                 }
180         }
181         return 0;
182 }
183 /*
184 static unsigned int pmon_read(int fd)
185 {
186         unsigned int pid;
187         read(fd, &pid, sizeof(pid));
188         return pid;
189 }
190 */
191
192 static int pmon_cb(void *data, Ecore_Fd_Handler * fd_handler)
193 {
194         int fd;
195         struct ss_main_data *ad = (struct ss_main_data *)data;
196         int dead_pid;
197
198         if (!ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)) {
199                 PRT_TRACE_ERR
200                     ("ecore_main_fd_handler_active_get error , return\n");
201                 return 1;
202         }
203
204         fd = ecore_main_fd_handler_fd_get(fd_handler);
205
206         if ((read(fd, &dead_pid, sizeof(dead_pid))) < 0) {
207                 PRT_TRACE_ERR("Reading DEAD_PID failed, Return");
208                 return 1;
209         }
210                 
211         print_pmon_state(dead_pid);
212         pmon_process(dead_pid, ad);
213
214         return 1;
215 }
216
217 int ss_pmon_init(struct ss_main_data *ad)
218 {
219         pmon_fd = open(PMON_DEV_NODE, O_RDONLY);
220         if (pmon_fd < 0) {
221                 PRT_TRACE_ERR("ss_pmon_init fd open failed");
222                 return -1;
223         }
224         ecore_main_fd_handler_add(pmon_fd, ECORE_FD_READ, pmon_cb, ad, NULL,
225                                   NULL);
226         return 0;
227 }