4 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
22 #include <iniparser.h>
31 #include <sys/prctl.h>
32 #include <sys/procfs.h>
34 #include <sys/types.h>
38 #include <pkgmgr-info.h>
39 #include <tzplatform_config.h>
42 #define LOG_TAG "CRASH_MANAGER"
45 #include "dbus_notify.h"
46 #include "shared/log.h"
47 #include "shared/config.h"
48 #include "shared/spawn.h"
49 #include "shared/util.h"
55 #define PKGNAME_MAX 128
57 #define CRASH_TEMP_SUBDIR "/temp/"
58 #define CRASH_PATH_SUBDIR "/dump/"
60 #define WAIT_FOR_OPT_TIMEOUT_SEC 60
62 #define MINICOREDUMPER_TIMEOUT_MS DEFAULT_COMMAND_TIMEOUT_MS
63 #define CRASH_STACK_TIMEOUT_MS DEFAULT_COMMAND_TIMEOUT_MS
64 #define ZIP_TIMEOUT_MS DEFAULT_COMMAND_TIMEOUT_MS
79 /* Configuration variables */
81 static char* crash_crash_path;
82 static char* crash_temp_path;
84 /* Paths and variables */
101 char appid[APPID_MAX];
102 char pkgid[PKGNAME_MAX];
104 char *sysassert_cs_path;
105 bool have_sysassert_report;
110 /* pkgmgrinfo filter list function for getting application ID */
111 static int appinfo_get_appid_func(pkgmgrinfo_appinfo_h handle,
116 int ret = pkgmgrinfo_appinfo_get_appid(handle, &str);
117 if (ret == PMINFO_R_OK && str)
118 (*(char **)user_data) = strdup(str);
123 /* get application ID by pkgmgrinfo filter */
124 static int get_appid(char *exepath, char *appid, int len)
126 pkgmgrinfo_appinfo_filter_h handle = NULL;
130 ret = pkgmgrinfo_appinfo_filter_create(&handle);
131 if (ret != PMINFO_R_OK) {
136 ret = pkgmgrinfo_appinfo_filter_add_string(handle, PMINFO_APPINFO_PROP_APP_EXEC, exepath);
137 if (ret != PMINFO_R_OK) {
142 ret = pkgmgrinfo_appinfo_filter_count(handle, &count);
143 if (ret != PMINFO_R_OK) {
153 ret = pkgmgrinfo_appinfo_filter_foreach_appinfo(handle, appinfo_get_appid_func, &aid);
154 if (ret != PMINFO_R_OK) {
159 snprintf(appid, len, "%s", aid);
165 pkgmgrinfo_appinfo_filter_destroy(handle);
170 /* get package ID by appid */
171 static int get_pkgid(char *appid, char *pkgid, int len)
173 pkgmgrinfo_appinfo_h handle = NULL;
177 ret = pkgmgrinfo_appinfo_get_appinfo(appid, &handle);
178 if (ret != PMINFO_R_OK) {
182 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkid);
183 if (ret != PMINFO_R_OK) {
187 snprintf(pkgid, len, "%s", pkid);
190 pkgmgrinfo_appinfo_destroy_appinfo(handle);
195 static int prepare_paths(void)
198 tmp_len = strlen(config.crash_root_path) + strlen(CRASH_PATH_SUBDIR);
199 crash_crash_path = (char*)malloc(tmp_len + 1);
200 if (crash_crash_path == NULL) {
201 _E("Couldn't allocate memory for crash_crash_path: %m\n");
204 snprintf(crash_crash_path, tmp_len + 1, "%s%s", config.crash_root_path, CRASH_PATH_SUBDIR);
206 tmp_len = strlen(config.crash_root_path) + strlen(CRASH_TEMP_SUBDIR);
207 crash_temp_path = (char*)malloc(tmp_len + 1);
208 if (crash_temp_path == NULL) {
209 _E("Couldn't allocate memory for crash_temp_path: %m\n");
212 snprintf(crash_temp_path, tmp_len + 1, "%s%s", config.crash_root_path, CRASH_TEMP_SUBDIR);
216 static int make_dump_dir(void)
220 if (!stat(crash_crash_path, &st)) {
221 if (!(st.st_mode & S_IFDIR)) {
222 _E("%s (not DIR) is already exist", crash_crash_path);
226 if (mkdir(crash_crash_path, 0775) < 0) {
227 _E("Failed to mkdir for %s", crash_crash_path);
232 if (!stat(crash_temp_path, &st)) {
233 if (!(st.st_mode & S_IFDIR)) {
234 _E("%s (not DIR) is already exist", crash_temp_path);
238 if (mkdir(crash_temp_path, 0775) < 0) {
239 _E("Failed to mkdir for %s", crash_temp_path);
247 static int get_cmd_info(struct crash_info *cinfo)
249 cinfo->cmd_line = get_cmd_line(cinfo->pid_info);
250 cinfo->cmd_path = get_exe_path(cinfo->pid_info);
252 return (cinfo->cmd_line != NULL && cinfo->cmd_path != NULL);
255 static int set_prstatus(struct crash_info *cinfo)
258 char prstatus_name[NAME_MAX+1];
260 ret = snprintf(prstatus_name, NAME_MAX, "/%d.prstatus", cinfo->pid_info);
262 _E("Failed to snprintf for prstatus path");
266 cinfo->prstatus_fd = shm_open(prstatus_name, O_RDWR | O_CREAT, 0600);
267 if (cinfo->prstatus_fd < 0) {
272 ret = shm_unlink(prstatus_name);
274 _E("shm_unlink: %m");
278 ret = fcntl(cinfo->prstatus_fd, F_GETFD);
284 ret = fcntl(cinfo->prstatus_fd, F_SETFD, ret & ~FD_CLOEXEC);
290 ret = ftruncate(cinfo->prstatus_fd, sizeof(struct elf_prstatus));
292 _E("ftruncate(): %m");
299 if (cinfo->prstatus_fd >= 0)
300 close(cinfo->prstatus_fd);
304 static int set_crash_info(struct crash_info *cinfo, int argc, char *argv[])
307 char *temp_dir_ret = NULL;
311 cinfo->pid_info = strtol(argv[1], NULL, 10);
312 cinfo->sig_info = atoi(argv[4]);
314 cinfo->tid_info = strtol(argv[6], NULL, 10);
316 cinfo->tid_info = find_crash_tid(cinfo->pid_info);
317 if (cinfo->tid_info < 0) {
319 cinfo->tid_info = cinfo->pid_info;
323 ret = get_cmd_info(cinfo);
325 _E("Failed to get command info");
329 cinfo->time_info = strtol(argv[5], NULL, 10);
330 localtime_r(&cinfo->time_info, &loc_tm);
331 strftime(date, sizeof(date), "%Y%m%d%H%M%S", &loc_tm);
333 if (asprintf(&cinfo->temp_dir, "%s/crash.XXXXXX", crash_temp_path) == -1) {
334 _E("Failed to asprintf for temp_dir");
335 cinfo->temp_dir = NULL;
339 temp_dir_ret = mkdtemp(cinfo->temp_dir);
340 if (!temp_dir_ret || access(temp_dir_ret, F_OK)) {
341 _E("Failed to mkdtemp for temp_dir");
345 if (asprintf(&cinfo->name, "%s_%d_%s", basename(cinfo->cmd_line),
346 cinfo->pid_info, date) == -1) {
347 _E("Failed to snprintf for name");
352 if (config.allow_zip)
353 ret = asprintf(&cinfo->result_path,
354 "%s/%s.zip", crash_crash_path, cinfo->name);
356 ret = asprintf(&cinfo->result_path,
357 "%s/%s", crash_crash_path, cinfo->name);
359 _E("Failed to asprintf for result path");
360 cinfo->result_path = NULL;
364 if (asprintf(&cinfo->pfx, "%s/%s", cinfo->temp_dir, cinfo->name) == -1) {
365 _E("Failed to asprintf for pfx");
369 ret = mkdir(cinfo->pfx, 0775);
371 _E("Failed to mkdir for %s", cinfo->pfx);
375 if (asprintf(&cinfo->info_path, "%s/%s.info", cinfo->pfx, cinfo->name) == -1) {
376 _E("Failed to asprintf for info path");
377 cinfo->info_path = NULL;
381 if (asprintf(&cinfo->core_path, "%s/%s.coredump", cinfo->pfx, cinfo->name) == -1) {
382 _E("Failed to asprintf for core path");
383 cinfo->core_path = NULL;
387 if (asprintf(&cinfo->log_path, "%s/%s.log", cinfo->pfx, cinfo->name) == -1) {
388 _E("Failed to asprintf for log path");
389 cinfo->log_path = NULL;
394 if (asprintf(&cinfo->sysassert_cs_path, "/tmp/crash_stack/%s_%d.info",
395 basename(cinfo->cmd_line), cinfo->pid_info) == -1) {
396 _E("Failed to snprintf for sys-assert callstack path");
397 cinfo->sysassert_cs_path = NULL;
401 if (set_prstatus(cinfo) < 0)
404 if (get_appid(cinfo->cmd_line, cinfo->appid, sizeof(cinfo->appid)) < 0) {
405 snprintf(cinfo->appid, sizeof(cinfo->appid), "%s", basename(cinfo->cmd_line));
406 snprintf(cinfo->pkgid, sizeof(cinfo->pkgid), "%s", basename(cinfo->cmd_line));
408 if (get_pkgid(cinfo->appid, cinfo->pkgid, sizeof(cinfo->pkgid)) < 0)
409 snprintf(cinfo->pkgid, sizeof(cinfo->pkgid), "%s", cinfo->appid);
415 remove_dir(cinfo->temp_dir, 1);
420 static int get_sysassert_cs(struct crash_info *cinfo)
423 char move_path[PATH_MAX];
425 if (access(cinfo->sysassert_cs_path, F_OK)) {
426 _E("The sys-assert cs file not found: %s",
427 cinfo->sysassert_cs_path);
428 cinfo->have_sysassert_report = 0;
431 cinfo->have_sysassert_report = 1;
433 ret = snprintf(move_path, sizeof(move_path), "%s/%s",
434 cinfo->pfx, basename(cinfo->sysassert_cs_path));
436 _E("Failed to snprintf for move path");
440 if (move_file(move_path, cinfo->sysassert_cs_path) < 0) {
441 _E("Failed to move %s to %s",
442 cinfo->sysassert_cs_path, move_path);
450 static void launch_crash_popup(struct crash_info *cinfo)
454 char *av[] = { "/usr/libexec/crash-popup-launch",
455 "--cmdline", cinfo->cmd_line,
456 "--cmdpath", cinfo->cmd_path,
459 spawn(av, NULL, spawn_nullstdfds, NULL, NULL, NULL);
462 static bool dump_system_state(const struct crash_info *cinfo, pid_t *pid)
464 char *av[] = {"/usr/bin/dump_systemstate", "-d", "-k", "-j", "-p", "-f", cinfo->log_path, NULL};
465 return spawn(av, NULL, NULL, NULL, pid, NULL);
468 static void save_so_info(const struct crash_info *cinfo)
470 char maps_path[PATH_MAX];
471 char so_info_path[PATH_MAX];
472 snprintf(maps_path, sizeof(maps_path), "/proc/%d/maps",
475 snprintf(so_info_path, sizeof(so_info_path),
476 "%s/%s.%s", cinfo->pfx, cinfo->name, "so_info");
478 get_and_save_so_info(maps_path, so_info_path);
481 /* remove a file whose name begins with 'beggining_of_name'. This is needed
482 * when we don't want to include coredump in report, but we only know the
483 * beginning of the coredump file name. */
484 static int remove_file_in_dir(const char *directory, const char *beginning_of_name)
487 int errno_unlink = 0;
489 DIR *dir = opendir(directory);
493 int dir_fd = dirfd(dir);
499 struct dirent* file_info;
500 while ((file_info = readdir(dir)) != NULL) {
501 if (strstr(file_info->d_name, beginning_of_name) == file_info->d_name) {
502 ret = unlinkat(dir_fd, file_info->d_name, 0);
503 errno_unlink = errno;
508 errno = errno_unlink; /* for %m */
513 // These macros are used in execute_minicoredump() and execute_crash_stack()
514 #define SNPRINTF_OR_EXIT_W(name, format, member) if (snprintf(name##_str, sizeof(name##_str), format, cinfo->member) < 0) goto out;
515 #define SNPRINTF_OR_EXIT(name, format) SNPRINTF_OR_EXIT_W(name, format, name##_info)
517 static bool execute_minicoredump(struct crash_info *cinfo, int *exit_code)
519 char *coredump_name = NULL;
520 char *prstatus_fd_str = NULL;
523 if (asprintf(&coredump_name, "%s.coredump", cinfo->name) == -1
524 || asprintf(&prstatus_fd_str, "%d", cinfo->prstatus_fd) == -1) {
525 _E("Unable to allocate memory");
529 char pid_str[11], uid_str[11], gid_str[11], sig_str[11], time_str[11];
531 SNPRINTF_OR_EXIT(pid, "%d")
532 SNPRINTF_OR_EXIT(uid, "%d")
533 SNPRINTF_OR_EXIT(gid, "%d")
534 SNPRINTF_OR_EXIT(sig, "%d")
535 SNPRINTF_OR_EXIT(time, "%ld")
537 /* Execute minicoredumper */
539 MINICOREDUMPER_BIN_PATH, // minicoredumper filename path
543 sig_str, // %s - number of signal
544 time_str, // %t - time of dump
545 "localhost", // %h - hostname
546 "core", // %e - exe name (need for result filename)
547 MINICOREDUMPER_CONFIG_PATH, // config file
549 cinfo->pfx, // temp dir
551 coredump_name, // coredump filename
557 is_ok = spawn_wait(args, NULL, NULL, NULL, MINICOREDUMPER_TIMEOUT_MS, exit_code);
559 /* Minicoredumper must be executed to dump at least PRSTATUS for
560 other tools, coredump, however, might have been disabled. */
561 if (!config.dump_core) {
562 if (remove_file_in_dir(cinfo->pfx, coredump_name) != 0)
563 _E("Saving core disabled - removing coredump %s/%s failed: %m",
564 cinfo->pfx, coredump_name);
566 _D("Saving core disabled - removed coredump %s/%s",
567 cinfo->pfx, coredump_name);
572 free(prstatus_fd_str);
577 static bool execute_crash_stack(const struct crash_info *cinfo, int *exit_code)
579 char pid_str[11], tid_str[11], sig_str[11], prstatus_fd_str[11];
582 SNPRINTF_OR_EXIT(pid, "%d")
583 SNPRINTF_OR_EXIT(tid, "%d")
584 SNPRINTF_OR_EXIT(sig, "%d")
585 SNPRINTF_OR_EXIT_W(prstatus_fd, "%d", prstatus_fd)
587 /* Execute crash-stack */
601 int fd = open(cinfo->info_path, O_WRONLY | O_CREAT, 0600);
603 _E("open %s error: %m", cinfo->info_path);
607 spawn_param_u param = { .int_val = fd };
608 is_ok = spawn_wait(args, NULL, spawn_setstdout, ¶m, CRASH_STACK_TIMEOUT_MS, exit_code);
615 #undef SNPRINTF_OR_EXIT
616 #undef SNPRINTF_OR_EXIT_W
618 static bool execute_crash_modules(struct crash_info *cinfo)
621 if (!execute_minicoredump(cinfo, &exit_code) || exit_code != 0) {
622 _E("Failed to run minicoredumper - can not continue");
627 /* Use process_vm_readv() version as fallback if sys-assert
628 * failed to generate report */
629 if (cinfo->have_sysassert_report)
632 execute_crash_stack(cinfo, NULL);
637 static int lock_dumpdir(void)
641 if ((fd = open(crash_crash_path, O_RDONLY | O_DIRECTORY)) < 0) {
642 _E("Failed to open %s", crash_crash_path);
646 if (flock(fd, LOCK_EX) < 0) {
647 _E("Failed to flock (LOCK)");
655 static void unlock_dumpdir(int fd)
657 if (flock(fd, LOCK_UN) < 0)
658 _E("Failed to unlink (UNLOCK)");
662 static int dump_filter(const struct dirent *de)
664 if (de->d_name[0] == '.')
669 static int mtime_cmp(const void *_a, const void *_b)
671 const struct file_info *a = _a;
672 const struct file_info *b = _b;
674 if (a->mtime < b->mtime)
676 if (a->mtime > b->mtime)
681 static int scan_dump(struct file_info **dump_list, off_t *usage)
683 struct file_info *temp_list;
684 struct dirent **scan_list = NULL;
686 int i, scan_num, dump_num = 0;
689 if ((fd = open(crash_crash_path, O_DIRECTORY)) < 0) {
690 _E("Failed to open %s", crash_crash_path);
694 scan_num = scandir(crash_crash_path, &scan_list, &dump_filter, NULL);
700 temp_list = (struct file_info *)calloc(scan_num,
701 sizeof(struct file_info));
703 _E("Failed to calloc for dump list");
707 for (i = 0; i < scan_num; i++) {
708 if (fstatat(fd, scan_list[i]->d_name, &st, 0) < 0) {
709 _E("Failed to fstatat");
713 if (asprintf(&(temp_list[dump_num].path), "%s/%s",
714 crash_crash_path, scan_list[i]->d_name) < 0) {
715 _E("Failed to asprintf");
719 if (scan_list[i]->d_type == DT_DIR) {
720 temp_list[dump_num].isdir = 1;
721 temp_list[dump_num].size =
722 get_directory_usage(temp_list[dump_num].path);
724 temp_list[dump_num].isdir = 0;
725 temp_list[dump_num].size = st.st_size;
727 temp_list[dump_num].mtime = st.st_mtime;
736 if (dump_num != scan_num) {
737 struct file_info *const tmp = (struct file_info *)realloc(temp_list,
738 dump_num * sizeof(struct file_info));
747 qsort(temp_list, dump_num, sizeof(struct file_info), mtime_cmp);
750 for (i = 0; i < dump_num; i++) {
751 _D("[%d] path: %s(%s), size: %zu kb, mtime: %s",
754 temp_list[i].isdir ? "DIR" : "FILE",
755 temp_list[i].size / 1024,
756 ctime(&(temp_list[i].mtime)));
757 *usage += temp_list[i].size;
759 *dump_list = temp_list;
761 for (i = 0; i < scan_num; i++)
769 static int check_disk_available(const char *path, int check_size)
771 struct statfs lstatfs;
777 if (statfs(path, &lstatfs) < 0)
779 avail_size = (int)(lstatfs.f_bavail * (lstatfs.f_bsize / 1024));
781 if (check_size > avail_size) {
782 _I("avail_size is (%d)", avail_size);
789 static int remove_file_info(struct file_info file)
792 return remove_dir(file.path, 1);
794 return unlink(file.path);
797 static void clean_dump(void)
799 struct file_info *dump_list = NULL;
800 int i, scan_num, dump_num, remove_flag;
804 scan_num = scan_dump(&dump_list, &usage);
810 cur_time = time(NULL);
812 for (i = 0; i < scan_num; i++) {
815 /* Retention time check */
816 if (config.max_retention_sec &&
817 dump_list[i].mtime > 0 &&
818 dump_list[i].mtime + config.max_retention_sec < cur_time)
819 remove_flag = RET_EXCEED;
820 /* Check the number of dumps */
821 else if (config.max_crash_dump &&
822 0 < dump_num && config.max_crash_dump < dump_num)
823 remove_flag = NUM_EXCEED;
824 /* Check the max system use size */
825 else if (config.system_max_use &&
826 0 < dump_num && config.system_max_use < usage / 1024)
827 remove_flag = USAGE_EXCEED;
829 switch (remove_flag) {
831 _I("Reached the maximum retention time %d, so remove (%s)",
832 config.max_retention_sec, dump_list[i].path);
835 _I("Reached the maximum number of dump %d/%d, so remove (%s)",
836 dump_num, config.max_crash_dump,
840 _I("Reached the maximum disk usage %" PRId64 "/%d kb, so remove (%s)",
841 usage / 1024, config.system_max_use,
851 if (remove_file_info(dump_list[i]) < 0) {
852 _E("Failed to remove %s", dump_list[i].path);
856 usage -= dump_list[i].size;
859 /* Check disk free space to keep */
860 if (config.system_keep_free &&
861 check_disk_available(config.crash_root_path,
862 config.system_keep_free) < 0) {
863 _I("Disk is not available! so set the maximum number of dump to 1");
864 config.max_crash_dump = 1;
867 for (i = 0; i < dump_num; i++)
868 free(dump_list[i].path);
872 static void compress(struct crash_info *cinfo)
875 char zip_path[PATH_MAX];
877 ret = snprintf(zip_path, sizeof(zip_path), "%s/report.zip",
880 _E("Failed to snprintf for zip path");
893 spawn_param_u param = { .char_ptr = cinfo->temp_dir };
894 (void)spawn_wait(args, NULL, spawn_chdir, ¶m, ZIP_TIMEOUT_MS, NULL);
896 if ((lock_fd = lock_dumpdir()) < 0)
898 if (!rename(zip_path, cinfo->result_path))
901 _E("Failed to move %s to %s", zip_path, cinfo->result_path);
902 unlock_dumpdir(lock_fd);
904 if (remove_dir(cinfo->temp_dir, 1) < 0)
905 _E("Failed to delete temp directory");
908 static void move_dump_data(const char *from_path, const struct crash_info *cinfo)
912 if ((lock_fd = lock_dumpdir()) < 0)
914 if (!rename(from_path, cinfo->result_path))
917 _E("Failed to move %s to %s",
918 from_path, cinfo->result_path);
919 unlock_dumpdir(lock_fd);
921 if (remove_dir(cinfo->temp_dir, 1) < 0)
922 _E("Failed to delete temp directory");
925 static int wait_for_opt(unsigned int timeout)
927 unsigned int count = 0;
929 while (check_disk_available(config.crash_root_path, 0) < 0 && count < timeout) {
930 log_kmsg("crash-manager: path %s is not available\n", config.crash_root_path);
934 if (count >= timeout) {
935 log_kmsg("crash-manager: timeout (%ds) while waiting for %s."
936 "Probably /opt is not mounted.\n", timeout, config.crash_root_path);
943 static void free_crash_info(struct crash_info *cinfo)
945 free(cinfo->cmd_line);
946 free(cinfo->cmd_path);
947 free(cinfo->temp_dir);
948 free(cinfo->result_path);
950 free(cinfo->info_path);
951 free(cinfo->core_path);
952 free(cinfo->log_path);
955 free(cinfo->sysassert_cs_path);
959 int main(int argc, char *argv[])
961 struct crash_info cinfo = {.prstatus_fd = -1};
963 /* Execute dump_systemstate in parallel */
964 static pid_t dump_state_pid;
965 int debug_mode = access(DEBUGMODE_PATH, F_OK) == 0;
969 * prctl(PR_SET_DUMPABLE, 0) is not neccessary. Kernel runs the
970 * crash-manager and sets RLIMIT_CORE to 1 for the process. This is special
971 * value that prevents from running crash-manager recursively.
974 if (!config_init(&config, CRASH_MANAGER_CONFIG_PATH)) {
979 if (!prepare_paths()) {
984 if (!wait_for_opt(WAIT_FOR_OPT_TIMEOUT_SEC)) {
989 /* Create crash directories */
990 if (make_dump_dir() < 0) {
996 if (set_crash_info(&cinfo, argc, argv) < 0) {
1002 /* Fetch callstack of sys-assert */
1003 get_sysassert_cs(&cinfo);
1006 if (config.report_type >= REP_TYPE_FULL) {
1007 /* Exec dump_systemstate */
1008 if (!dump_system_state(&cinfo, &dump_state_pid)) {
1010 _E("Failed to get system state report");
1015 /* Exec crash modules */
1016 if (!execute_crash_modules(&cinfo)) {
1018 _E("Failed to get basic crash information");
1022 if (config.report_type >= REP_TYPE_FULL) {
1023 /* Save shared objects info (file names, bulid IDs, rpm package names) */
1024 save_so_info(&cinfo);
1026 /* Wait dump_system_state */
1027 wait_for_pid(dump_state_pid, NULL);
1029 /* Tar compression */
1030 if (config.allow_zip)
1033 move_dump_data(cinfo.pfx, &cinfo);
1035 free(cinfo.result_path);
1036 if (asprintf(&cinfo.result_path, "%s/%s.info",
1037 crash_crash_path, cinfo.name) == -1) {
1038 cinfo.result_path = NULL;
1039 _E("asprintf() error: %m");
1043 move_dump_data(cinfo.info_path, &cinfo);
1046 struct NotifyParams notify_params = {
1047 .prstatus_fd = cinfo.prstatus_fd,
1048 .pid = cinfo.pid_info,
1049 .tid = cinfo.tid_info,
1050 .cmd_name = basename(cinfo.cmd_line),
1051 .cmd_path = cinfo.cmd_path,
1052 .report_path = cinfo.result_path,
1053 .appid = cinfo.appid,
1054 .pkgid = cinfo.pkgid
1057 send_notify(¬ify_params);
1059 /* Release the core pipe as passed by kernel, allowing another
1060 * coredump to be handled.
1062 * Due to usage of core_pipe_limit there is limited number of
1063 * crash-manager processes that kernel is going to invoke
1064 * concurrently. As the next and last step is a _synchronous_
1065 * call to crash-popup we close the descriptor here.
1067 * Note: for VIP processes this will likely cause the system
1068 * to reboot without showing popup.
1070 close(STDIN_FILENO);
1072 /* launch crash-popup only if the .debugmode file exists */
1074 launch_crash_popup(&cinfo);
1077 _I("Exiting with exit code %d", res);
1078 if (cinfo.prstatus_fd >= 0)
1079 close(cinfo.prstatus_fd);
1080 free(crash_temp_path);
1081 free(crash_crash_path);
1082 config_free(&config);
1084 free_crash_info(&cinfo);