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.
23 #include <iniparser.h>
32 #include <sys/prctl.h>
33 #include <sys/procfs.h>
35 #include <sys/types.h>
39 #include <pkgmgr-info.h>
40 #include <tzplatform_config.h>
43 #define LOG_TAG "CRASH_MANAGER"
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 functions below
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 void launch_dbus_notify(struct crash_info *cinfo)
521 char pid_str[11], tid_str[11];
522 char *prstatus_fd_str = NULL;
524 if (asprintf(&prstatus_fd_str, "%d", cinfo->prstatus_fd) == -1) {
525 _E("Unable to allocate memory: %m");
529 SNPRINTF_OR_EXIT(pid, "%d")
530 SNPRINTF_OR_EXIT(tid, "%d")
532 char *av[] = { "/usr/libexec/crash-notify-send",
533 "--cmdline", cinfo->cmd_line,
534 "--cmdpath", cinfo->cmd_path,
537 "--appid", cinfo->appid,
538 "--pkgid", cinfo->pkgid,
539 "--reportpath", cinfo->result_path,
540 "--prstatus_fd", prstatus_fd_str,
543 spawn(av, NULL, NULL, NULL, NULL, NULL);
545 free(prstatus_fd_str);
548 static bool execute_minicoredump(struct crash_info *cinfo, int *exit_code)
550 char *coredump_name = NULL;
551 char *prstatus_fd_str = NULL;
554 if (asprintf(&coredump_name, "%s.coredump", cinfo->name) == -1
555 || asprintf(&prstatus_fd_str, "%d", cinfo->prstatus_fd) == -1) {
556 _E("Unable to allocate memory");
560 char pid_str[11], uid_str[11], gid_str[11], sig_str[11], time_str[11];
562 SNPRINTF_OR_EXIT(pid, "%d")
563 SNPRINTF_OR_EXIT(uid, "%d")
564 SNPRINTF_OR_EXIT(gid, "%d")
565 SNPRINTF_OR_EXIT(sig, "%d")
566 SNPRINTF_OR_EXIT(time, "%ld")
568 /* Execute minicoredumper */
570 MINICOREDUMPER_BIN_PATH, // minicoredumper filename path
574 sig_str, // %s - number of signal
575 time_str, // %t - time of dump
576 "localhost", // %h - hostname
577 "core", // %e - exe name (need for result filename)
578 MINICOREDUMPER_CONFIG_PATH, // config file
580 cinfo->pfx, // temp dir
582 coredump_name, // coredump filename
588 is_ok = spawn_wait(args, NULL, NULL, NULL, MINICOREDUMPER_TIMEOUT_MS, exit_code);
590 /* Minicoredumper must be executed to dump at least PRSTATUS for
591 other tools, coredump, however, might have been disabled. */
592 if (!config.dump_core) {
593 if (remove_file_in_dir(cinfo->pfx, coredump_name) != 0)
594 _E("Saving core disabled - removing coredump %s/%s failed: %m",
595 cinfo->pfx, coredump_name);
597 _D("Saving core disabled - removed coredump %s/%s",
598 cinfo->pfx, coredump_name);
603 free(prstatus_fd_str);
608 static bool execute_crash_stack(const struct crash_info *cinfo, int *exit_code)
610 char pid_str[11], tid_str[11], sig_str[11], prstatus_fd_str[11];
613 SNPRINTF_OR_EXIT(pid, "%d")
614 SNPRINTF_OR_EXIT(tid, "%d")
615 SNPRINTF_OR_EXIT(sig, "%d")
616 SNPRINTF_OR_EXIT_W(prstatus_fd, "%d", prstatus_fd)
618 /* Execute crash-stack */
632 int fd = open(cinfo->info_path, O_WRONLY | O_CREAT, 0600);
634 _E("open %s error: %m", cinfo->info_path);
638 spawn_param_u param = { .int_val = fd };
639 is_ok = spawn_wait(args, NULL, spawn_setstdout, ¶m, CRASH_STACK_TIMEOUT_MS, exit_code);
646 #undef SNPRINTF_OR_EXIT
647 #undef SNPRINTF_OR_EXIT_W
649 static bool execute_crash_modules(struct crash_info *cinfo)
652 if (!execute_minicoredump(cinfo, &exit_code) || exit_code != 0) {
653 _E("Failed to run minicoredumper - can not continue");
658 /* Use process_vm_readv() version as fallback if sys-assert
659 * failed to generate report */
660 if (cinfo->have_sysassert_report)
663 execute_crash_stack(cinfo, NULL);
668 static int lock_dumpdir(void)
672 if ((fd = open(crash_crash_path, O_RDONLY | O_DIRECTORY)) < 0) {
673 _E("Failed to open %s", crash_crash_path);
677 if (flock(fd, LOCK_EX) < 0) {
678 _E("Failed to flock (LOCK)");
686 static void unlock_dumpdir(int fd)
688 if (flock(fd, LOCK_UN) < 0)
689 _E("Failed to unlink (UNLOCK)");
693 static int dump_filter(const struct dirent *de)
695 if (de->d_name[0] == '.')
700 static int mtime_cmp(const void *_a, const void *_b)
702 const struct file_info *a = _a;
703 const struct file_info *b = _b;
705 if (a->mtime < b->mtime)
707 if (a->mtime > b->mtime)
712 static int scan_dump(struct file_info **dump_list, off_t *usage)
714 struct file_info *temp_list;
715 struct dirent **scan_list = NULL;
717 int i, scan_num, dump_num = 0;
720 if ((fd = open(crash_crash_path, O_DIRECTORY)) < 0) {
721 _E("Failed to open %s", crash_crash_path);
725 scan_num = scandir(crash_crash_path, &scan_list, &dump_filter, NULL);
731 temp_list = (struct file_info *)calloc(scan_num,
732 sizeof(struct file_info));
734 _E("Failed to calloc for dump list");
738 for (i = 0; i < scan_num; i++) {
739 if (fstatat(fd, scan_list[i]->d_name, &st, 0) < 0) {
740 _E("Failed to fstatat");
744 if (asprintf(&(temp_list[dump_num].path), "%s/%s",
745 crash_crash_path, scan_list[i]->d_name) < 0) {
746 _E("Failed to asprintf");
750 if (scan_list[i]->d_type == DT_DIR) {
751 temp_list[dump_num].isdir = 1;
752 temp_list[dump_num].size =
753 get_directory_usage(temp_list[dump_num].path);
755 temp_list[dump_num].isdir = 0;
756 temp_list[dump_num].size = st.st_size;
758 temp_list[dump_num].mtime = st.st_mtime;
767 if (dump_num != scan_num) {
768 struct file_info *const tmp = (struct file_info *)realloc(temp_list,
769 dump_num * sizeof(struct file_info));
778 qsort(temp_list, dump_num, sizeof(struct file_info), mtime_cmp);
781 for (i = 0; i < dump_num; i++) {
782 _D("[%d] path: %s(%s), size: %zu kb, mtime: %s",
785 temp_list[i].isdir ? "DIR" : "FILE",
786 temp_list[i].size / 1024,
787 ctime(&(temp_list[i].mtime)));
788 *usage += temp_list[i].size;
790 *dump_list = temp_list;
792 for (i = 0; i < scan_num; i++)
800 static int check_disk_available(const char *path, int check_size)
802 struct statfs lstatfs;
808 if (statfs(path, &lstatfs) < 0)
810 avail_size = (int)(lstatfs.f_bavail * (lstatfs.f_bsize / 1024));
812 if (check_size > avail_size) {
813 _I("avail_size is (%d)", avail_size);
820 static int remove_file_info(struct file_info file)
823 return remove_dir(file.path, 1);
825 return unlink(file.path);
828 static void clean_dump(void)
830 struct file_info *dump_list = NULL;
831 int i, scan_num, dump_num, remove_flag;
835 scan_num = scan_dump(&dump_list, &usage);
841 cur_time = time(NULL);
843 for (i = 0; i < scan_num; i++) {
846 /* Retention time check */
847 if (config.max_retention_sec &&
848 dump_list[i].mtime > 0 &&
849 dump_list[i].mtime + config.max_retention_sec < cur_time)
850 remove_flag = RET_EXCEED;
851 /* Check the number of dumps */
852 else if (config.max_crash_dump &&
853 0 < dump_num && config.max_crash_dump < dump_num)
854 remove_flag = NUM_EXCEED;
855 /* Check the max system use size */
856 else if (config.system_max_use &&
857 0 < dump_num && config.system_max_use < usage / 1024)
858 remove_flag = USAGE_EXCEED;
860 switch (remove_flag) {
862 _I("Reached the maximum retention time %d, so remove (%s)",
863 config.max_retention_sec, dump_list[i].path);
866 _I("Reached the maximum number of dump %d/%d, so remove (%s)",
867 dump_num, config.max_crash_dump,
871 _I("Reached the maximum disk usage %" PRId64 "/%d kb, so remove (%s)",
872 usage / 1024, config.system_max_use,
882 if (remove_file_info(dump_list[i]) < 0) {
883 _E("Failed to remove %s", dump_list[i].path);
887 usage -= dump_list[i].size;
890 /* Check disk free space to keep */
891 if (config.system_keep_free &&
892 check_disk_available(config.crash_root_path,
893 config.system_keep_free) < 0) {
894 _I("Disk is not available! so set the maximum number of dump to 1");
895 config.max_crash_dump = 1;
898 for (i = 0; i < dump_num; i++)
899 free(dump_list[i].path);
903 static void compress(struct crash_info *cinfo)
906 char zip_path[PATH_MAX];
908 ret = snprintf(zip_path, sizeof(zip_path), "%s/report.zip",
911 _E("Failed to snprintf for zip path");
924 spawn_param_u param = { .char_ptr = cinfo->temp_dir };
925 (void)spawn_wait(args, NULL, spawn_chdir, ¶m, ZIP_TIMEOUT_MS, NULL);
927 if ((lock_fd = lock_dumpdir()) < 0)
929 if (!rename(zip_path, cinfo->result_path))
932 _E("Failed to move %s to %s", zip_path, cinfo->result_path);
933 unlock_dumpdir(lock_fd);
935 if (remove_dir(cinfo->temp_dir, 1) < 0)
936 _E("Failed to delete temp directory");
939 static void move_dump_data(const char *from_path, const struct crash_info *cinfo)
943 if ((lock_fd = lock_dumpdir()) < 0)
945 if (!rename(from_path, cinfo->result_path))
948 _E("Failed to move %s to %s",
949 from_path, cinfo->result_path);
950 unlock_dumpdir(lock_fd);
952 if (remove_dir(cinfo->temp_dir, 1) < 0)
953 _E("Failed to delete temp directory");
956 static int wait_for_opt(unsigned int timeout)
958 unsigned int count = 0;
960 while (check_disk_available(config.crash_root_path, 0) < 0 && count < timeout) {
961 log_kmsg("crash-manager: path %s is not available\n", config.crash_root_path);
965 if (count >= timeout) {
966 log_kmsg("crash-manager: timeout (%ds) while waiting for %s."
967 "Probably /opt is not mounted.\n", timeout, config.crash_root_path);
974 static void free_crash_info(struct crash_info *cinfo)
976 free(cinfo->cmd_line);
977 free(cinfo->cmd_path);
978 free(cinfo->temp_dir);
979 free(cinfo->result_path);
981 free(cinfo->info_path);
982 free(cinfo->core_path);
983 free(cinfo->log_path);
986 free(cinfo->sysassert_cs_path);
990 int main(int argc, char *argv[])
992 struct crash_info cinfo = {.prstatus_fd = -1};
994 /* Execute dump_systemstate in parallel */
995 static pid_t dump_state_pid;
996 int debug_mode = access(DEBUGMODE_PATH, F_OK) == 0;
1000 * prctl(PR_SET_DUMPABLE, 0) is not neccessary. Kernel runs the
1001 * crash-manager and sets RLIMIT_CORE to 1 for the process. This is special
1002 * value that prevents from running crash-manager recursively.
1005 if (!config_init(&config, CRASH_MANAGER_CONFIG_PATH)) {
1010 if (!prepare_paths()) {
1015 if (!wait_for_opt(WAIT_FOR_OPT_TIMEOUT_SEC)) {
1020 /* Create crash directories */
1021 if (make_dump_dir() < 0) {
1026 /* Set crash info */
1027 if (set_crash_info(&cinfo, argc, argv) < 0) {
1033 /* Fetch callstack of sys-assert */
1034 get_sysassert_cs(&cinfo);
1037 if (config.report_type >= REP_TYPE_FULL) {
1038 /* Exec dump_systemstate */
1039 if (!dump_system_state(&cinfo, &dump_state_pid)) {
1041 _E("Failed to get system state report");
1046 /* Exec crash modules */
1047 if (!execute_crash_modules(&cinfo)) {
1049 _E("Failed to get basic crash information");
1053 if (config.report_type >= REP_TYPE_FULL) {
1054 /* Save shared objects info (file names, bulid IDs, rpm package names) */
1055 save_so_info(&cinfo);
1057 /* Wait dump_system_state */
1058 wait_for_pid(dump_state_pid, NULL);
1060 /* Tar compression */
1061 if (config.allow_zip)
1064 move_dump_data(cinfo.pfx, &cinfo);
1066 free(cinfo.result_path);
1067 if (asprintf(&cinfo.result_path, "%s/%s.info",
1068 crash_crash_path, cinfo.name) == -1) {
1069 cinfo.result_path = NULL;
1070 _E("asprintf() error: %m");
1074 move_dump_data(cinfo.info_path, &cinfo);
1077 /* Release the core pipe as passed by kernel, allowing another
1078 * coredump to be handled.
1080 * Due to usage of core_pipe_limit there is limited number of
1081 * crash-manager processes that kernel is going to invoke
1082 * concurrently. As the next and last step is a _synchronous_
1083 * call to crash-popup we close the descriptor here.
1085 * Note: for VIP processes this will likely cause the system
1086 * to reboot without showing popup.
1088 close(STDIN_FILENO);
1090 launch_dbus_notify(&cinfo);
1092 /* launch crash-popup only if the .debugmode file exists */
1094 launch_crash_popup(&cinfo);
1097 _I("Exiting with exit code %d", res);
1098 if (cinfo.prstatus_fd >= 0)
1099 close(cinfo.prstatus_fd);
1100 free(crash_temp_path);
1101 free(crash_crash_path);
1102 config_free(&config);
1104 free_crash_info(&cinfo);