4 * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: YoungHun Kim <yh8004.kim@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include "muse_server_private.h"
24 #define U32BITS 0xffffffff
25 #define MAX_FILE_NUM 3
26 #define MAX_SIZE 33554432
28 #define BUILD_ID "BUILD_ID"
31 static gboolean _ms_log_pid_is_valid(pid_t pid);
32 static void _ms_log_latest_msgs(ms_log_t *log);
33 static void _ms_log_pid_time(ms_log_t* log, int pid);
34 static void _ms_log_cmdline(ms_log_t* log, int pid);
35 static void _ms_log_process_info(ms_log_t* log, int pid);
36 static void _ms_log_api_info(ms_log_t *log);
37 static void _ms_log_binary_info(ms_log_t *log);
38 static int _ms_fd_set_block(int fd);
39 static int _ms_log_open_work(const char *path);
40 static void _ms_log_create_fd(ms_log_t *log);
41 static void _ms_log_set_fd(ms_log_t *log);
42 static void _ms_log_cache_latest_msg(ms_log_t *log, int pid, char *msg);
44 static gboolean _ms_log_pid_is_valid(pid_t pid)
46 char log_buf[MUSE_MSG_LEN_MAX];
48 muse_return_val_if_fail(ms_is_log_enabled(), FALSE);
50 snprintf(log_buf, sizeof(log_buf), "/proc/%d", (int)pid);
52 if (access(log_buf, F_OK) != 0) {
53 LOGD("%d process doesn't exist", (int)pid);
60 static void _ms_log_latest_msgs(ms_log_t *log)
64 muse_return_if_fail(ms_is_log_enabled());
65 muse_return_if_fail(log);
67 g_mutex_lock(&log->lock);
69 if (muse_core_fd_is_valid(log->fd)) {
70 for (idx = log->cur_idx; idx < MUSE_LOG_MSG_NUM; idx++)
71 ms_log_write(log->latest_msgs[idx]);
73 for (idx = 0; idx < log->cur_idx; idx++)
74 ms_log_write(log->latest_msgs[idx]);
77 g_mutex_unlock(&log->lock);
80 static void _ms_log_pid_time(ms_log_t *log, int pid)
82 char log_buf[MUSE_MSG_LEN_MAX];
83 char time_buf[MUSE_MSG_TIME_LEN];
85 muse_return_if_fail(ms_is_log_enabled());
86 muse_return_if_fail(log);
87 muse_return_if_fail(muse_core_fd_is_valid(log->fd));
88 muse_return_if_fail(_ms_log_pid_is_valid(pid));
90 muse_core_get_cur_time(NULL, time_buf);
91 snprintf(log_buf, MUSE_MSG_LEN_MAX, "[PID] %d %s", pid, time_buf);
93 ms_log_write(log_buf);
96 static void _ms_log_cmdline(ms_log_t *log, int pid)
98 char log_buf[MUSE_MSG_LEN_MAX];
101 muse_return_if_fail(ms_is_log_enabled());
102 muse_return_if_fail(log);
103 muse_return_if_fail(muse_core_fd_is_valid(log->fd));
104 muse_return_if_fail(_ms_log_pid_is_valid(pid));
106 snprintf(log_buf, sizeof(log_buf), "/proc/%d/cmdline", pid);
107 fp = fopen(log_buf, "r");
109 size_t size = fread(log_buf, sizeof(char), MUSE_MSG_LEN_MAX, fp);
110 log_buf[size] = '\0';
112 ms_log_write(log_buf);
117 static void _ms_log_process_info(ms_log_t *log, int pid)
119 char log_buf[MUSE_MSG_LEN_MAX];
122 muse_return_if_fail(ms_is_log_enabled());
123 muse_return_if_fail(log);
124 muse_return_if_fail(muse_core_fd_is_valid(log->fd));
125 muse_return_if_fail(_ms_log_pid_is_valid(pid));
127 snprintf(log_buf, sizeof(log_buf), "/bin/ps -Lo pcpu,pmem,tid,comm -p %d", pid);
128 fp = popen(log_buf, "r");
130 ms_log_write(log_buf);
132 while (fgets(log_buf, MUSE_MSG_LEN_MAX, fp)) {
133 if (write(log->fd, log_buf, strlen(log_buf)) == WRITE_FAIL)
134 LOGE("fail to write command info to logfile");
137 if (pclose(fp) == -1)
138 LOGE("fail to pclose");
142 static void _ms_log_api_info(ms_log_t *log)
145 char log_buf[MUSE_MSG_LEN_MAX];
149 muse_return_if_fail(ms_is_log_enabled());
150 muse_return_if_fail(log);
151 muse_return_if_fail(muse_core_fd_is_valid(log->fd));
153 for (idx = 0; idx < ms_config_get_host_cnt(); idx++) {
154 ms_module_get_dllsym_value(idx, DISPATCHER_PTR, &ptr);
155 memset(&info, 0, sizeof(info));
156 if (dladdr((const void *) ptr, &info) && info.dli_sname) {
157 snprintf(log_buf, sizeof(log_buf), "[The latest called api name] %s", info.dli_sname);
158 ms_log_write(log_buf);
163 static void _ms_log_binary_info(ms_log_t *log)
165 char log_buf[MUSE_MSG_LEN_MAX];
171 muse_return_if_fail(ms_is_log_enabled());
172 muse_return_if_fail(log);
173 muse_return_if_fail(muse_core_fd_is_valid(log->fd));
175 fp = fopen("/etc/tizen-release", "r");
176 muse_return_if_fail(fp);
178 while (fgets(log_buf, MUSE_MSG_LEN_MAX, fp)) {
179 label = strtok_r(log_buf, delimiter, &ptr);
181 if (strncmp(label, BUILD_ID, strlen(BUILD_ID)) == 0) {
182 value = strtok_r(NULL, delimiter, &ptr);
186 LOGE("strtok_r (value) returns null");
189 LOGE("strtok_r (label) returns null");
196 static int _ms_fd_set_block(int fd)
201 muse_return_val_if_fail(ms_is_log_enabled(), MM_ERROR_NOT_SUPPORT_API);
203 flags = fcntl(fd, F_GETFL);
204 ret = fcntl(fd, F_SETFL, flags & (U32BITS ^ O_NONBLOCK));
206 muse_core_update_fd_state(fd);
211 static int _ms_log_open_work(const char *path)
213 muse_return_val_if_fail(path, MM_ERROR_INVALID_ARGUMENT);
214 muse_core_remove_symlink(path);
215 return open(path, O_CREAT | O_APPEND | O_WRONLY | O_NONBLOCK, 0644);
218 static void _ms_log_create_fd(ms_log_t *log)
220 int selected_idx = 0;
223 char file[MAX_FILE_NUM][MUSE_MSG_LEN];
225 muse_return_if_fail(ms_is_log_enabled());
226 muse_return_if_fail(log);
228 for (idx = 0; idx < MAX_FILE_NUM; idx++)
229 snprintf(file[idx], strlen(MUSE_LOG_FILE) + 3, "%s.%d", MUSE_LOG_FILE, idx);
231 for (idx = 0; idx < MAX_FILE_NUM; idx++) {
232 if (access(file[idx], F_OK) == 0) { /* if 0, then there is file */
233 if (stat(file[idx], &st) == MUSE_ERR) {
234 LOGE("stat %s fail", file[idx]);
237 log->size = st.st_size;
238 if (log->size > MAX_SIZE) {
239 selected_idx = (idx + 1) % MAX_FILE_NUM;
250 LOGD("filename: %s", file[selected_idx]);
251 /* open log file again */
252 log->fd = _ms_log_open_work(file[selected_idx]);
253 if (!muse_core_fd_is_valid(log->fd))
254 LOGE("couldn't open log file %d", log->fd);
256 LOGD("log fd : %d", log->fd);
259 static void _ms_log_set_fd(ms_log_t *log)
261 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
263 if (!ms_is_log_enabled())
266 muse_return_if_fail(log);
268 _ms_log_create_fd(log);
270 muse_return_if_fail(muse_core_fd_is_valid(log->fd));
272 if (fcntl(log->fd, F_SETFD, FD_CLOEXEC) < 0) {
273 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
274 LOGE("unable to set CLO_EXEC on log fd %d: %s", log->fd, err_msg);
277 (void) _ms_fd_set_block(log->fd);
280 static void _ms_log_cache_latest_msg(ms_log_t *log, int pid, char *msg)
282 char time_buf[MUSE_MSG_TIME_LEN];
283 muse_return_if_fail(msg);
284 muse_return_if_fail(log);
286 g_mutex_lock(&log->lock);
288 muse_core_get_cur_time(NULL, time_buf);
289 snprintf(log->latest_msgs[log->cur_idx], MUSE_MSG_LEN_MAX, "[P%5d] %s %s", pid, time_buf, msg);
291 log->cur_idx = (log->cur_idx + 1) % MUSE_LOG_MSG_NUM;
293 g_mutex_unlock(&log->lock);
296 void ms_log_init(ms_log_t *log)
298 muse_return_if_fail(log);
300 g_mutex_init(&log->lock);
304 void ms_log_deinit(ms_log_t *log)
308 muse_return_if_fail(log);
310 muse_return_if_fail(ms_is_log_enabled());
311 g_mutex_clear(&log->lock);
318 void ms_log_save_addr_name(int pid, gpointer addr)
322 muse_return_if_fail(ms_get_instance());
323 muse_return_if_fail(ms_is_log_enabled());
324 muse_return_if_fail(addr);
326 memset(&info, 0, sizeof(info));
328 if (dladdr((const void *) addr, &info) && info.dli_sname)
329 _ms_log_cache_latest_msg(ms_get_instance()->log, pid, (char *)info.dli_sname);
331 LOGE("fail to log api name");
334 void ms_log_debug_pid_info(int pid)
336 ms_log_t *log = NULL;
338 muse_return_if_fail(ms_get_instance());
339 muse_return_if_fail(ms_is_log_enabled());
341 log = ms_get_instance()->log;
342 muse_return_if_fail(log);
345 _ms_log_pid_time(log, pid);
348 _ms_log_cmdline(log, pid);
351 _ms_log_process_info(log, pid);
354 _ms_log_api_info(log);
357 _ms_log_binary_info(log);
360 _ms_log_latest_msgs(log);
363 void ms_log_write(char *buf)
365 ms_log_t *log = NULL;
367 muse_return_if_fail(ms_get_instance());
369 log = ms_get_instance()->log;
371 muse_return_if_fail(ms_is_log_enabled());
372 muse_return_if_fail(log);
373 muse_return_if_fail(muse_core_fd_is_valid(log->fd));
374 muse_return_if_fail(buf);
376 if (write(log->fd, buf, strlen(buf)) == WRITE_FAIL)
377 LOGE("There was an error writing module pid to logfile");
378 else if (write(log->fd, "\n", 1) == WRITE_FAIL)
379 LOGE("fail to write new line character");