From a75cc01442d61e8e479873c574712438858808e2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=C5=81ukasz=20Stelmach?= Date: Tue, 7 Aug 2018 15:51:52 +0200 Subject: [PATCH 01/16] crash-stack: Use dlog-based macros for logging messages MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Change-Id: I16bbfd1f6437b106e187633ddd00e65bbe74738f Signed-off-by: Łukasz Stelmach --- src/crash-manager/crash-manager.c | 6 +++ src/crash-stack/CMakeLists.txt | 6 ++- src/crash-stack/crash-stack-libunw.c | 3 ++ src/crash-stack/crash-stack.c | 33 +++++++------ src/crash-stack/mem_map.c | 89 ++++++++++++++++++------------------ src/crash-stack/proc.c | 36 +++++++++------ src/crash-stack/unwind.c | 52 ++++++++++----------- 7 files changed, 121 insertions(+), 104 deletions(-) diff --git a/src/crash-manager/crash-manager.c b/src/crash-manager/crash-manager.c index bdc2469..6ecb416 100644 --- a/src/crash-manager/crash-manager.c +++ b/src/crash-manager/crash-manager.c @@ -269,31 +269,37 @@ static int set_prstatus() ret = snprintf(prstatus_name, NAME_MAX, "/%s.prstatus", crash_info.pid_info); if (ret < 0) { + _E("Failed to snprintf for prstatus path"); goto close_fd; } crash_info.prstatus_fd = shm_open(prstatus_name, O_RDWR | O_CREAT, 0600); if (crash_info.prstatus_fd < 0) { + _E("shm_open: %s", strerror(errno)); goto close_fd; } ret = shm_unlink(prstatus_name); if (ret < 0) { + _E("shm_unlink: %s", strerror(errno)); goto close_fd; } ret = fcntl(crash_info.prstatus_fd, F_GETFD); if (ret < 0) { + _E("fcntl(): %s", strerror(errno)); goto close_fd; } ret = fcntl(crash_info.prstatus_fd, F_SETFD, ret & ~FD_CLOEXEC); if (ret < 0) { + _E("fcntl(): %s", strerror(errno)); goto close_fd; } ret = ftruncate(crash_info.prstatus_fd, sizeof(struct elf_prstatus)); if (ret < 0) { + _E("ftruncate(): %s", strerror(errno)); goto close_fd; } diff --git a/src/crash-stack/CMakeLists.txt b/src/crash-stack/CMakeLists.txt index 29e1fb4..ddeba3a 100644 --- a/src/crash-stack/CMakeLists.txt +++ b/src/crash-stack/CMakeLists.txt @@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 2.8.11) set(CRASH_STACK_BIN "crash-stack") # Common source code files +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src) set(CRASH_STACK_SRCS crash-stack.c crash-stack-libunw.c unwind.c proc.c mem_map.c) # Add architecture dependent source files @@ -28,10 +29,11 @@ add_executable(${CRASH_STACK_BIN} ${CRASH_STACK_SRCS}) include(FindPkgConfig) pkg_check_modules(LIBUNWIND REQUIRED libunwind-generic) -set_property(TARGET ${CRASH_STACK_BIN} APPEND_STRING PROPERTY COMPILE_FLAGS ${LIBUNWIND_CFLAGS_OTHER}) +pkg_check_modules(DLOG REQUIRED dlog) +set_property(TARGET ${CRASH_STACK_BIN} APPEND_STRING PROPERTY COMPILE_FLAGS ${LIBUNWIND_CFLAGS} ${DLOG_CFLAGS}) # Linking -target_link_libraries(${CRASH_STACK_BIN} ${LIBUNWIND_LIBRARIES} ${EBL_LIBRARY} elf dl stdc++) +target_link_libraries(${CRASH_STACK_BIN} ${DLOG_LIBRARIES} ${LIBUNWIND_LIBRARIES} ${EBL_LIBRARY} elf dl stdc++) # Installing install(TARGETS ${CRASH_STACK_BIN} DESTINATION libexec) diff --git a/src/crash-stack/crash-stack-libunw.c b/src/crash-stack/crash-stack-libunw.c index 1875a05..1ed1fa9 100644 --- a/src/crash-stack/crash-stack-libunw.c +++ b/src/crash-stack/crash-stack-libunw.c @@ -26,6 +26,9 @@ #include "crash-stack.h" +#define LOG_TAG "CRASH_STACK" +#include "shared/log.h" + #define MAXPROCNAMELEN 1024 void _create_crash_stack(Dwfl *dwfl, pid_t pid, Callstack *callstack, elf_gregset_t *regs) diff --git a/src/crash-stack/crash-stack.c b/src/crash-stack/crash-stack.c index c78a847..6a2fca7 100644 --- a/src/crash-stack/crash-stack.c +++ b/src/crash-stack/crash-stack.c @@ -48,6 +48,8 @@ #include "crash-stack.h" +#define LOG_TAG "CRASH_STACK" +#include "shared/log.h" #define BUF_SIZE (BUFSIZ) #define HEXA 16 @@ -117,7 +119,7 @@ static int __get_registers_fd(pid_t pid, int fd) char *registers = _crash_stack_get_memory_for_registers(&size); if (NULL == registers) { - fprintf(errfile, "Cannot get memory for registers (not implemented for this architecture\n"); + _E("Cannot get memory for registers (not implemented for this architecture"); return -1; } @@ -177,7 +179,7 @@ static void __crash_stack_print_signal(int signo) #undef DEF_STR if (SIGHUP > signo || signo > SIGSYS) { - fprintf(errfile, "Invalid signal number: %d\n", signo); + _E("Invalid signal number: %d", signo); return; } @@ -302,7 +304,7 @@ static void __crash_stack_print_threads(FILE* outputfile, pid_t pid, pid_t tid) /* print thread */ dir = opendir(task_path); if (!dir) { - fprintf(errfile, "[crash-stack] cannot open %s\n", task_path); + _E("opendir(%s): %s", task_path, strerror(errno)); } else { while ((dentry = readdir(dir))) { if (strcmp(dentry->d_name, ".") == 0 || @@ -333,7 +335,7 @@ static void __crash_stack_print_maps(FILE* outputfile, pid_t pid) snprintf(file_path, PATH_MAX, "/proc/%d/maps", pid); if ((fd = open(file_path, O_RDONLY)) < 0) { - fprintf(errfile, "[crash-stack] cannot open %s\n", file_path); + _E("open(%s): %s", file_path, strerror(errno)); } else { /* parsing the maps to get code segment address*/ head = get_addr_list_from_maps(fd); @@ -396,7 +398,7 @@ static struct addr_node *get_addr_list_from_maps(int fd) PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (t_node == NULL) { - fprintf(errfile, "error : mmap\n"); + _E("mmap(): %s", strerror(errno)); return NULL; } memcpy(t_node->perm, perm, PERM_LEN+1); @@ -486,7 +488,7 @@ static void __crash_stack_print_meminfo(FILE* outputfile, pid_t pid) fprintf(outputfile, "\nMemory information\n"); if ((fd = open("/proc/meminfo", O_RDONLY)) < 0) { - fprintf(errfile, "[crash-stack] cannot open /proc/meminfo\n"); + _E("open(/proc/meminfo): %s", strerror(errno)); } else { while (fgets_fd(linebuf, BUF_SIZE, fd) != NULL) { sscanf(linebuf, "%16s %16s %*s", infoname, memsize); @@ -506,7 +508,7 @@ static void __crash_stack_print_meminfo(FILE* outputfile, pid_t pid) snprintf(file_path, PATH_MAX, "/proc/%d/status", pid); if ((fd = open(file_path, O_RDONLY)) < 0) { - fprintf(errfile, "[crash-stack] cannot open %s\n", file_path); + _E("open(%s): %s", file_path, strerror(errno)); } else { while (fgets_fd(linebuf, BUF_SIZE, fd) != NULL) { sscanf(linebuf, "%16s %16s %*s", infoname, memsize); @@ -565,7 +567,7 @@ static void __print_buffer_info(FILE* bufferfile, FILE *outputfile) char buf[1024]; if (fseek(bufferfile, 0, SEEK_SET) < 0) { - fprintf(errfile, "Failed to fseek\n"); + _E("fseek(): %s", strerror(errno)); return; } while (!(feof(bufferfile) || ferror(bufferfile)) && (cnt = fread(buf, sizeof(char), sizeof(buf), bufferfile)) != 0) { @@ -588,12 +590,12 @@ static int check_thread_wchan(int pid, int tid) snprintf(path, PATH_MAX, "/proc/%d/task/%d/wchan", pid, tid); fd = open(path, O_RDONLY); if (fd == -1) { - fprintf(errfile, "[crash-stack] cannot open %s\n", path); + _E("open(%s): %s", path, strerror(errno)); return -errno; } cnt = read(fd, buf, sizeof(buf)); if (cnt == -1 || cnt == sizeof(buf)) { - fprintf(errfile, "[crash-stack] read %s error\n", path); + _E("read(%s): %s", path, strerror(errno)); close(fd); return -errno; } @@ -629,7 +631,7 @@ static int find_crash_tid(int pid) if (threadnum > 1) { dir = opendir(task_path); if (!dir) { - fprintf(errfile, "[crash-stack] cannot open %s\n", task_path); + _E("opendir(%s): %s", task_path, strerror(errno)); return -1; } else { while ((entry = readdir(dir)) != NULL) { @@ -684,6 +686,7 @@ int main(int argc, char **argv) break; case OPT_ERRFILE: errfile = fopen(optarg, "w"); + _W("--erroutput is deprecated"); break; case OPT_PRSTATUS_FD: prstatus_fd = strtol(optarg, &p, 10); @@ -703,13 +706,13 @@ int main(int argc, char **argv) mode_t oldmode = umask(0077); if (mkstemp(bufferfile_path) < 0) { - fprintf(errfile, "Failed to create buffer file.\n"); + _E("mkstemp(%s): %s", bufferfile_path, strerror(errno)); return errno; } umask(oldmode); if ((bufferfile = fopen(bufferfile_path, "w+")) == NULL) { - fprintf(errfile, "Failed to open buffer file.\n"); + _E("fopen(%s): %s", bufferfile_path, strerror(errno)); return errno; } unlink(bufferfile_path); @@ -734,9 +737,9 @@ int main(int argc, char **argv) __crash_stack_print_maps(bufferfile, pid); if (pid <= 1) { - fprintf(errfile, - "Usage: %s [--output file] [--erroutput file] [--pid [--tid ]]\n", + _E( "Usage: %s [--output file] [--erroutput file] [--pid [--tid ]]", argv[0]); + return 1; } diff --git a/src/crash-stack/mem_map.c b/src/crash-stack/mem_map.c index 4703a74..f74bc23 100644 --- a/src/crash-stack/mem_map.c +++ b/src/crash-stack/mem_map.c @@ -27,6 +27,8 @@ * DAMAGE. */ +#define LOG_TAG "CRASH_STACK" +#include "shared/log.h" #include "mem_map.h" #include "proc.h" @@ -158,13 +160,13 @@ static int mem_region_add_data_chunk(struct mem_region *region, for (i = 0; i < region->num_data_chunks; ++i) { if (in(chunk->start, (*cur)->start, (*cur)->length) || - fprintf(stderr, "error: overlapping chunks: existing: %p-%p " - "new: %p-%p\n", - (*cur)->start, - (*cur)->start + (*cur)->length, - chunk->start, - chunk_ceil); in(chunk_ceil, (*cur)->start, (*cur)->length)) { + _E("Overlapping chunks: existing: %p-%p " + "new: %p-%p", + (*cur)->start, + (*cur)->start + (*cur)->length, + chunk->start, + chunk_ceil); return -1; } if ((*cur)->start > chunk->start) @@ -193,9 +195,9 @@ static struct mem_data_chunk *mem_region_alloc_chunk(struct mem_region *region, chunk->length = (size_t)end - (size_t)start; rc = posix_memalign((void **)&chunk->data, align, chunk->length); if (rc < 0) { - perror("posix_memalign"); int err = errno; free(chunk); + _E("posix_memalign:%s", strerror(err)); return NULL; } @@ -267,8 +269,8 @@ static int mem_region_create_data_chunk_index(struct mem_region *region) region->data_index[i++] = cur; if (i > (int)region->num_data_chunks) { - fprintf(stderr, "region %p: num_data_chunks=%zd but cur != NULL\n", - region, region->num_data_chunks); + _E("region %p: num_data_chunks=%zd but cur != NULL", + region, region->num_data_chunks); mem_region_print(region); return -1; } @@ -327,9 +329,8 @@ static int mem_region_map_file(struct mem_region *region) size_t length = region->length; if (region->path == NULL || *region->path == '\0') { - fprintf(stderr, "trying to map file for region %p-%p " - "with empty path\n", - region->start, region->start + region->length); + _E("Trying to map file for region %p-%p with an empty path", + region->start, region->start + region->length); return -1; } @@ -337,12 +338,13 @@ static int mem_region_map_file(struct mem_region *region) if (region->fd < 0) { int err = errno; mem_region_print(region); + _E("open(%s):%s", region->path, strerror(err)); return -1; } if (fstat(region->fd, &stat_buf) < 0) { int err = errno; - fprintf(stderr, "failed to stat file %s: %s\n", region->path, strerror(err)); + _E("Unable to stat file %s: %s", region->path, strerror(err)); return -1; } @@ -362,15 +364,16 @@ static int mem_region_map_file(struct mem_region *region) if (data == MAP_FAILED) { int err = errno; - fprintf(stderr, "failed to mmap file %s (length 0x%zx, read, offset " - "0x%zx): %s\n", region->path, region->length, region->offset, - strerror(err)); + _E("Unable to mmap file %s (length 0x%zx, read, offset 0x%zx): %s", + region->path, region->length, region->offset, + strerror(err)); return -1; } region->data_head = malloc(sizeof(struct mem_data_chunk)); if (region->data_head == NULL) { int err = errno; + _E("Unable to allocate memory:%s", strerror(err)); munmap(data, length); return -1; } @@ -382,6 +385,7 @@ static int mem_region_map_file(struct mem_region *region) region->data_index = malloc(sizeof(struct mem_data_chunk**)); if (region->data_index == NULL){ int err = errno; + _E("Unable to allocate memory:%s", strerror(err)); free(region->data_head); munmap(data, length); return -1; @@ -407,6 +411,7 @@ static int mem_region_init_vdso(struct mem_region *region) region->data_index = malloc(sizeof(struct mem_data_chunk**)); if (region->data_index == NULL) { int err = errno; + _E("Unable to allocate memory:%s", strerror(err)); return -1; } *region->data_index = region->data_head; @@ -422,6 +427,7 @@ static int mem_region_init_vsyscall(struct mem_region *region) region->data_head = malloc(sizeof(struct mem_data_chunk)); if (region->data_head == NULL) { int err = errno; + _E("Unable to allocate memory:%s", strerror(err)); return -1; } mem_data_chunk_init(region->data_head); @@ -431,6 +437,7 @@ static int mem_region_init_vsyscall(struct mem_region *region) region->data_index = malloc(sizeof(struct mem_data_chunk**)); if (region->data_index == NULL) { int err = errno; + _E("Unable to allocate memory:%s", strerror(err)); return -1; } *region->data_index = region->data_head; @@ -462,11 +469,9 @@ struct mem_data_chunk *mem_region_find_data_chunk( if (region->data_index == NULL) { if (region->num_data_chunks) { - fprintf(stderr, - "error: region %p-%p is not indexed but " - "attempting to read word\n", - region->start, - region->start + region->length); + _E("Region %p-%p is not indexed but attempting to read word", + region->start, + region->start + region->length); } return NULL; } @@ -492,10 +497,9 @@ static int mem_region_read_word(struct mem_region *region, switch (region->type) { case MEM_REGION_TYPE_EMPTY: - fprintf(stderr, - "error: trying to read word from empty region %p-%p\n", - region->start, - region->start + region->length); + _E("Trying to read word from empty region %p-%p", + region->start, + region->start + region->length); return -1; case MEM_REGION_TYPE_DELETED: @@ -532,15 +536,14 @@ static int mem_region_read_word(struct mem_region *region, if (!opt_verbose) return -1; - fprintf(stderr, - "no chunk of memory containing %p at region %p-%p\n", - addr, region->start, region->start + region->length); + _E("No chunk of memory containing %p at region %p-%p", + addr, region->start, region->start + region->length); mem_region_print(region); for (i = 0; i < region->num_data_chunks; ++i) { struct mem_data_chunk *chunk = region->data_index[i]; - fprintf(stderr, "chunk %zd: start %p length 0x%zx data %p\n", - i, chunk->start, chunk->length, chunk->data); + _E("Chunk %zd: start %p length 0x%zx data %p", + i, chunk->start, chunk->length, chunk->data); } return -1; } @@ -602,12 +605,12 @@ int mem_map_add_region(struct mem_map *map, struct mem_region *region) if (in(region->start, (*cur)->start, (*cur)->length) || in(region_ceil, (*cur)->start, (*cur)->length)) { - fprintf(stderr, "error: overlapping regions: existing: %p-%p " - "new: %p-%p\n", - (*cur)->start, - (*cur)->start+(*cur)->length, - region->start, - region_ceil); + _E("Overlapping regions: existing: %p-%p " + "new: %p-%p", + (*cur)->start, + (*cur)->start+(*cur)->length, + region->start, + region_ceil); return -1; } if ((*cur)->start > region->start) @@ -658,8 +661,7 @@ static struct mem_region *mem_map_find_region(struct mem_map *map, void *addr) if (map->list_index == NULL) { if (map->num_regions) { - fprintf(stderr, - "error: map is not indexed but attempting to find region\n"); + _E("map is not indexed but attempting to find region"); } return NULL; } @@ -671,9 +673,7 @@ static struct mem_region *mem_map_find_region(struct mem_map *map, void *addr) addr_region_compar); if (region_ptr == NULL) { - fprintf(stderr, - "cannot find region of memory containing %p\n", - addr); + _E("cannot find region of memory containing %p", addr); region = NULL; } else { region = *region_ptr; @@ -688,7 +688,7 @@ struct mem_region *mem_map_get_file_region(struct mem_map *map, void *addr) struct mem_region *region; if ((region = mem_map_find_region(map, addr)) == NULL) { - fprintf(stderr, "cannot get file region\n"); + _E("Unable to get file region"); return NULL; } @@ -696,8 +696,8 @@ struct mem_region *mem_map_get_file_region(struct mem_map *map, void *addr) region->type != MEM_REGION_TYPE_DELETED && region->type != MEM_REGION_TYPE_VDSO && region->type != MEM_REGION_TYPE_VSYSCALL) { - fprintf(stderr, "get file region: unexpected region type %s\n", - str_mem_region_type(region->type)); + _E("Unexpected region type %s", + str_mem_region_type(region->type)); mem_region_print(region); return NULL; } @@ -762,7 +762,6 @@ void mem_map_print(const struct mem_map *map) { struct mem_region *region; - fprintf(stderr, "mem map with %zd regions\n", map->num_regions); region = map->list_head; for (; region != NULL; region = region->next) mem_region_print(region); diff --git a/src/crash-stack/proc.c b/src/crash-stack/proc.c index 457f530..f082440 100644 --- a/src/crash-stack/proc.c +++ b/src/crash-stack/proc.c @@ -49,6 +49,9 @@ #include #include +#define LOG_TAG "CRASH_STACK" +#include "shared/log.h" + #ifndef SYS_process_vm_readv #if defined(__i386) #define SYS_process_vm_readv 365 @@ -92,7 +95,7 @@ int proc_state(int pid) snprintf(buf, sizeof(buf), "/proc/%d/status", pid); if ((f = fopen(buf, "r")) == NULL) { - fprintf(stderr, "cannot open %s: %s\n", buf, strerror(errno)); + _E("Cannot open %s: %s", buf, strerror(errno)); return -1; } @@ -124,16 +127,18 @@ struct mem_map *create_maps(int pid) capacity = 0x100000; buf = calloc(1, capacity); if (buf == NULL) { + _E("Unable to allocate memory: %s", strerror(errno)); return NULL; } snprintf(buf, capacity, "/proc/%d/maps", pid); if ((f = fopen(buf, "r")) == NULL) { - fprintf(stderr, "cannot open %s: %s\n", buf, strerror(errno)); + _E("Cannot open %s: %s", buf, strerror(errno)); goto create_maps_end; } map = malloc(sizeof(struct mem_map)); if (map == NULL){ + _E("Unable to allocate memory: %s", strerror(errno)); goto create_maps_end; } mem_map_init(map); @@ -155,6 +160,7 @@ struct mem_map *create_maps(int pid) capacity *= 2; buf = realloc(buf, capacity); if (buf == NULL) { + _E("Unable to reallocate memory: %s", strerror(errno)); mem_map_destroy(map); map = NULL; goto create_maps_end; @@ -183,13 +189,14 @@ struct mem_map *create_maps(int pid) path); if (scan < 10) { - fprintf(stderr, "warning: unable to parse maps " - "entry '%s' (read %d)\n", str, scan); + _W("Unable to parse maps " + "entry '%s' (read %d)", str, scan); break; } region = malloc(sizeof(struct mem_region)); if (region == NULL) { + _E("Unable to allocate memory: %s", strerror(errno)); mem_map_destroy(map); map = NULL; break; @@ -290,7 +297,7 @@ char *get_thread_states(const int *tids, int n) for (i = 0; i < n; ++i) { int state = proc_state(tids[i]); if (state < 0) { - fprintf(stderr, "warning: could not get state of thread %d\n", + _W("Could not get state of thread %d", tids[i]); res[i] = '?'; continue; @@ -315,7 +322,7 @@ int adjust_threads(int *tids, int nr_tids, int *user_tids, } if (!found) { if (n || (user_tids[i] > nr_tids) || (user_tids[i] <= 0)) { - fprintf(stderr, "unexpected thread %d\n", user_tids[i]); + _E("Unexpected thread %d", user_tids[i]); return -1; } } else { @@ -404,7 +411,7 @@ static int copy_memory_process_vm_readv(int pid, if (errno == ENOSYS) rc = ENOSYS; else - perror("process_vm_readv"); + _E("process_vm_readv: %s", strerror(errno)); goto process_vm_readv_end; } @@ -417,9 +424,9 @@ static int copy_memory_process_vm_readv(int pid, } if (seg_count < 0) { - fprintf(stderr, "unknown number of bytes returned by " + _E("Unknown number of bytes returned by " "process_vm_readv: bytes_read=%zd " - "bytes_total=%zd seg_count=%d\n", + "bytes_total=%zd seg_count=%d", bytes_read, bytes_total, seg_count); goto process_vm_readv_end; } @@ -452,8 +459,7 @@ static int copy_memory_proc_mem(int pid, struct mem_data_chunk **frames, snprintf(fname, sizeof(fname), "/proc/%d/mem", pid); if ((fd = open(fname, O_RDONLY)) == -1) { - fprintf(stderr, "cannot open %s\n", fname); - perror(fname); + _E("Cannot open %s: %s", fname, strerror(errno)); return -1; } @@ -466,8 +472,8 @@ static int copy_memory_proc_mem(int pid, struct mem_data_chunk **frames, ssize_t rd = pread(fd, to, count, from); if (rd == -1) { - fprintf(stderr, "pread() at %s:0x%lx (#%d) failed: %s [%d]\n", - fname, from, i, strerror(errno), errno); + _E("pread() at %s:0x%lx (#%d) failed: %s [%d]", + fname, from, i, strerror(errno), errno); goto proc_mem_end; } @@ -492,8 +498,8 @@ int copy_memory(int pid, struct mem_data_chunk **frames, int n_frames) int rc = copy_memory_process_vm_readv(pid, frames, n_frames); if (rc == ENOSYS) { if (opt_verbose) { - fprintf(stderr, "process_vm_readv is not supported, falling " - "back to /proc/pid/mem\n"); + _E("process_vm_readv is not supported, falling " + "back to /proc/pid/mem"); } } else { return rc; diff --git a/src/crash-stack/unwind.c b/src/crash-stack/unwind.c index a2b140d..c98433b 100644 --- a/src/crash-stack/unwind.c +++ b/src/crash-stack/unwind.c @@ -43,6 +43,9 @@ #include "proc.h" #include "crash-stack.h" +#define LOG_TAG "CRASH_STACK" +#include "shared/log.h" + size_t stack_size = 0xa00000; /* @@ -79,10 +82,10 @@ static Elf *elf_start(int fd, char *image, uint64_t size) if (fd > 0) { if ((elf = elf_begin(fd, TBSTACK_ELF_C_READ, NULL)) == NULL) - fprintf(stderr, "error:elf_begin: %s\n", elf_errmsg(elf_errno())); + _E("elf_begin: %s", elf_errmsg(elf_errno())); } else { if ((elf = elf_memory(image, size)) == NULL) - fprintf(stderr, "error:elf_memory: %s\n", elf_errmsg(elf_errno())); + _E("elf_memory: %s", elf_errmsg(elf_errno())); } return elf; @@ -105,13 +108,13 @@ static int find_exidx(int fd, char *image, uint64_t size, return -1; if (gelf_getehdr(elf, &ehdr) == NULL) { - fprintf(stderr, "error:elf_getehdr: %s\n", elf_errmsg(elf_errno())); + _E("elf_getehdr: %s", elf_errmsg(elf_errno())); goto find_exidx_end; } while ((scn = elf_nextscn(elf, scn)) != NULL) { if (gelf_getshdr(scn, &shdr) == NULL) { - fprintf(stderr, "error:elf_getshdr: %s\n", elf_errmsg(elf_errno())); + _E("elf_getshdr: %s", elf_errmsg(elf_errno())); break; } @@ -119,7 +122,7 @@ static int find_exidx(int fd, char *image, uint64_t size, Elf_Data *data = NULL; if ((data = elf_getdata(scn, data)) == NULL) { - fprintf(stderr, "error:elf_getdata: %s\n", elf_errmsg(elf_errno())); + _E("elf_getdata: %s", elf_errmsg(elf_errno())); break; } @@ -185,8 +188,8 @@ static ssize_t dw_get_value(char *data, unsigned char enc, break; default: - fprintf(stderr, "unsupported encoding in " - ".eh_frame_hdr: %d\n", (int)enc); + _E("unsupported encoding in " + ".eh_frame_hdr: %d", (int)enc); return -1; } @@ -223,7 +226,7 @@ static int parse_eh_frame_hdr(char *data, size_t pos, pos += 4; if (version != 1) { - fprintf(stderr, "error:unknown .ehf_frame_hdr version %d\n", version); + _E("unknown .ehf_frame_hdr version %d", version); return -1; } @@ -258,7 +261,7 @@ static int find_eh_frame_hdr(int fd, char *image, uint64_t size, return -1; if (gelf_getehdr(elf, &ehdr) == NULL) { - fprintf(stderr, "elf_getehdr: %s\n", elf_errmsg(elf_errno())); + _E("elf_getehdr: %s", elf_errmsg(elf_errno())); goto elf_section_offset_end; } @@ -266,7 +269,7 @@ static int find_eh_frame_hdr(int fd, char *image, uint64_t size, char *str; if (gelf_getshdr(scn, &shdr) == NULL) { - fprintf(stderr, "elf_nextscn: %s\n", elf_errmsg(elf_errno())); + _E("elf_getshdr: %s", elf_errmsg(elf_errno())); break; } @@ -275,7 +278,7 @@ static int find_eh_frame_hdr(int fd, char *image, uint64_t size, Elf_Data *data = NULL; if ((data = elf_getdata(scn, data)) == NULL) { - fprintf(stderr, "elf_getdata: %s\n", elf_errmsg(elf_errno())); + _E("elf_getdata: %s", elf_errmsg(elf_errno())); break; } @@ -328,6 +331,7 @@ static int push_symbol(struct symbols *array, const GElf_Sym *s) array->s_cap <<= 1; new_data = malloc(sizeof(GElf_Sym) * array->s_cap); if (new_data == NULL) { + _E("malloc(): %s", strerror(errno)); return -1; } memcpy(new_data, array->s_data, sizeof(GElf_Sym) * (array->s_size-1)); @@ -419,7 +423,7 @@ static char *proc_name(int fd, char *image, size_t size, uint64_t load, GElf_Shdr shdr; if (gelf_getshdr(scn, &shdr) == NULL) { - fprintf(stderr, "elf_nextscn: %s\n", elf_errmsg(elf_errno())); + _E("elf_nextscn: %s", elf_errmsg(elf_errno())); goto proc_name_end; } @@ -428,7 +432,7 @@ static char *proc_name(int fd, char *image, size_t size, uint64_t load, int symbol_count; if ((data = elf_getdata(scn, data)) == NULL) { - fprintf(stderr, "elf_getdata: %s\n", elf_errmsg(elf_errno())); + _E("elf_getdata: %s", elf_errmsg(elf_errno())); goto proc_name_end; } @@ -437,7 +441,7 @@ static char *proc_name(int fd, char *image, size_t size, uint64_t load, GElf_Sym s; if (gelf_getsym(data, i, &s) == NULL) { - fprintf(stderr, "elf_getsym: %s\n", + _E("elf_getsym: %s", elf_errmsg(elf_errno())); rc = -1; goto proc_name_end; @@ -457,7 +461,7 @@ static char *proc_name(int fd, char *image, size_t size, uint64_t load, if (addr >= s.st_value && addr < (s.st_value + s.st_size)) { str = elf_strptr(elf, shdr.sh_link, s.st_name); if (str == NULL) { - fprintf(stderr, "elf_strptr #1: %s\n", + _E("elf_strptr #1: %s", elf_errmsg(elf_errno())); rc = -1; goto proc_name_end; @@ -493,7 +497,7 @@ static char *proc_name(int fd, char *image, size_t size, uint64_t load, if (cur->st_value <= addr && addr < next->st_value) { str = elf_strptr(elf, cur->st_shndx, cur->st_name); if (str == NULL) { - fprintf(stderr, "elf_strptr #2: %s\n", + _E("elf_strptr #2: %s", elf_errmsg(elf_errno())); rc = -1; goto proc_name_end; @@ -599,7 +603,6 @@ static void put_unwind_info(unw_addr_space_t as, (void) as; (void) pip; (void) arg; - fprintf(debug, "%s is not supported\n", __func__); } /* @@ -611,7 +614,6 @@ static int get_dyn_info_list_addr(unw_addr_space_t as, (void) as; (void) dilap; (void) arg; - fprintf(debug, "%s is not supported\n", __func__); return -UNW_ENOINFO; } @@ -625,7 +627,7 @@ static int access_mem(unw_addr_space_t as, unw_word_t addr, (void) arg; if (write) { - fprintf(stderr, "access_mem: requested write, rejecting\n"); + _E("access_mem: requested write, rejecting"); return -UNW_EINVAL; } @@ -644,11 +646,9 @@ static int access_reg(unw_addr_space_t as, unw_regnum_t reg, (void) write; (void) arg; - fprintf(debug, "debug: requested register %d\n", reg); - fflush(debug); if (write) { - fprintf(debug, "requested to write into register\n"); + _E("requested to write into register"); return -UNW_EINVAL; } @@ -732,8 +732,7 @@ static int access_fpreg(unw_addr_space_t as, unw_regnum_t regnum, (void) write; (void) arg; - fprintf(debug, "access_fpreg is not supported\n"); - fflush(debug); + _D("access_fpreg is not supported"); return -UNW_ENOINFO; } @@ -746,8 +745,7 @@ static int resume(unw_addr_space_t as, unw_cursor_t *cp, void *arg) (void) cp; (void) arg; - fprintf(debug, "resume is not supported\n"); - fflush(debug); + _D("resume is not supported"); return -UNW_ENOINFO; } @@ -842,7 +840,7 @@ void *_TB_create (pid_t pid) { long label; if ((page = sysconf(_SC_PAGESIZE)) < 0) { - perror("get pagesize"); + _E("sysconf(_SC_PAGESIZE): %s", strerror(errno)); return NULL; } --page; -- 2.7.4 From 482161bdef079c6caf072d54dcd92d630dd5baa7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=C5=81ukasz=20Stelmach?= Date: Mon, 6 Aug 2018 14:09:34 +0200 Subject: [PATCH 02/16] log: Enable logging messages to a FILE* instead of dlog MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit For development purposes it is possible to write log messages to a FILE* instead of dlog. To do it add the line below before including log.h. #define LOG_FILE stderr You may to choose any other FILE* than stderr but you need to make sure it is available. Change-Id: I500fd774b95d84b78c8bc46d4274ac1f94947f9c Signed-off-by: Łukasz Stelmach --- src/shared/log.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/shared/log.h b/src/shared/log.h index 6a38a4c..bee783b 100644 --- a/src/shared/log.h +++ b/src/shared/log.h @@ -25,6 +25,33 @@ #endif #include +#ifdef LOG_FILE +#include +#include +#undef LOG_ +static inline char __dlog_prio(int prio) +{ + static const char pri_table[DLOG_PRIO_MAX] = { + [DLOG_UNKNOWN] = '?', + [DLOG_DEFAULT] = '?', + [DLOG_VERBOSE] = 'V', + [DLOG_DEBUG] = 'D', + [DLOG_INFO] = 'I', + [DLOG_WARN] = 'W', + [DLOG_ERROR] = 'E', + [DLOG_FATAL] = 'F', + [DLOG_SILENT] = 'S', + }; + return pri_table[(prio >= 0 && prio < DLOG_PRIO_MAX) ? prio : DLOG_UNKNOWN]; +} +#define LOG_(id, prio, tag, fmt, arg...) \ + ({ do { \ + fprintf(LOG_FILE, "%c/%-8s(%5d): %s: %s(%d) > " fmt "\n", \ + __dlog_prio(prio), tag, getpid(), \ + __MODULE__, __func__, __LINE__, ##arg); \ + } while (0); }) +#endif + #define _D(fmt, arg...) SLOGD(fmt, ##arg) #define _I(fmt, arg...) SLOGI(fmt, ##arg) #define _W(fmt, arg...) SLOGW(fmt, ##arg) -- 2.7.4 From b59c099801cbfaa2207e8bd909213fc7d9f03cbe Mon Sep 17 00:00:00 2001 From: Mateusz Moscicki Date: Fri, 10 Aug 2018 10:41:39 +0200 Subject: [PATCH 03/16] Save full cmd_line Change-Id: I98ac10c8931a0e1c0b586c6e116279faa6ef9d44 --- src/crash-manager/crash-manager.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/crash-manager/crash-manager.c b/src/crash-manager/crash-manager.c index 6ecb416..922f99e 100644 --- a/src/crash-manager/crash-manager.c +++ b/src/crash-manager/crash-manager.c @@ -94,7 +94,7 @@ static struct crash_info { char *pid_info; char *tid_info; char *sig_info; - char cmd_name[FILENAME_MAX]; + char cmd_line[PATH_MAX]; char cmd_path[PATH_MAX]; char time_info[80]; char temp_dir[PATH_MAX]; @@ -236,8 +236,9 @@ static int get_cmd_info(struct crash_info *cinfo) goto error; } - snprintf(cinfo->cmd_name, sizeof(cinfo->cmd_name), "%s", - basename(cmdline)); + cmdline[ret] = '\0'; + + strncpy(cinfo->cmd_line, cmdline, sizeof(cinfo->cmd_line)); snprintf(exe_link, sizeof(exe_link), "/proc/%s/exe", cinfo->pid_info); @@ -347,7 +348,7 @@ static int set_crash_info(int argc, char *argv[]) } ret = snprintf(crash_info.name, sizeof(crash_info.name), "%s_%s_%s", - crash_info.cmd_name, + basename(crash_info.cmd_line), crash_info.pid_info, crash_info.time_info); if (ret < 0) { @@ -405,7 +406,7 @@ static int set_crash_info(int argc, char *argv[]) ret = snprintf(crash_info.sysassert_cs_path, sizeof(crash_info.sysassert_cs_path), "/tmp/crash_stack/%s_%s.info", - crash_info.cmd_name, crash_info.pid_info); + basename(crash_info.cmd_line), crash_info.pid_info); if (ret < 0) { _E("Failed to snprintf for sys-assert callstack path"); goto rm_temp; @@ -472,7 +473,7 @@ static void launch_crash_popup(void) builder = g_variant_builder_new(G_VARIANT_TYPE("a{ss}")); g_variant_builder_add(builder, "{ss}", "_SYSPOPUP_CONTENT_", "crash"); g_variant_builder_add(builder, "{ss}", "_PROCESS_NAME_", - crash_info.cmd_name); + basename(crash_info.cmd_line)); g_variant_builder_add(builder, "{ss}", "_EXEPATH_", crash_info.cmd_path); parameters = g_variant_new("(a{ss})", builder); g_variant_builder_unref(builder); -- 2.7.4 From 2aa848d9b6d683a42eb1478c1d9965c921901418 Mon Sep 17 00:00:00 2001 From: Mateusz Moscicki Date: Thu, 2 Aug 2018 11:16:56 +0200 Subject: [PATCH 04/16] Add DBus signal emitting after report save Interface: "org.tizen.system.crash.Crash" Path: "/org/Tizen/System/Crash/Crash" Signal: "ProcessCrashed" Message (signature "sssssiia{sv}"), contains: * process name * exe path * appid * pkgid * report path * PID * TID * dictionary a{sv} contains registers values depends on the architecture: * for x86: * x86.eip * for x86_64: * x86_64.rip * for armv7l: * arm.pc * arm.lr * for aarch64: * aarch64.pc * aarch64.lr Change-Id: I081a3f4982e2f0d4b01fd665b4dffcd3bab847f4 --- packaging/crash-worker.spec | 1 + src/crash-manager/CMakeLists.txt | 2 + src/crash-manager/crash-manager.c | 115 +++++++++++++++++++++ src/crash-manager/dbus_notify.c | 212 ++++++++++++++++++++++++++++++++++++++ src/crash-manager/dbus_notify.h | 43 ++++++++ 5 files changed, 373 insertions(+) create mode 100644 src/crash-manager/dbus_notify.c create mode 100644 src/crash-manager/dbus_notify.h diff --git a/packaging/crash-worker.spec b/packaging/crash-worker.spec index 5d41038..92eac66 100644 --- a/packaging/crash-worker.spec +++ b/packaging/crash-worker.spec @@ -23,6 +23,7 @@ BuildRequires: pkgconfig(capi-system-info) BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(rpm) BuildRequires: cmake +BuildRequires: pkgconfig(pkgmgr-info) BuildRequires: pkgconfig(libunwind-generic) %if "%{TIZEN_FEATURE_PTRACE_CALLSTACK}" == "on" diff --git a/src/crash-manager/CMakeLists.txt b/src/crash-manager/CMakeLists.txt index d70dde2..2b7e6e4 100644 --- a/src/crash-manager/CMakeLists.txt +++ b/src/crash-manager/CMakeLists.txt @@ -17,6 +17,7 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src) SET(CRASH_MANAGER_SRCS crash-manager.c so-info.c + dbus_notify.c ${CMAKE_SOURCE_DIR}/src/shared/util.c ) @@ -26,6 +27,7 @@ pkg_check_modules(crash-manager_pkgs REQUIRED libtzplatform-config iniparser gio-2.0 + pkgmgr-info rpm ) diff --git a/src/crash-manager/crash-manager.c b/src/crash-manager/crash-manager.c index 922f99e..2c351fe 100644 --- a/src/crash-manager/crash-manager.c +++ b/src/crash-manager/crash-manager.c @@ -35,10 +35,12 @@ #include #include #include +#include #include "crash-manager.h" #include "so-info.h" #include "shared/log.h" #include "shared/util.h" +#include "dbus_notify.h" #undef LOG_TAG #define LOG_TAG "CRASH_MANAGER" @@ -63,6 +65,9 @@ #define MAX_CRASH_DUMP 0 #define ALLOW_ZIP true +#define APPID_MAX 128 +#define PKGNAME_MAX 128 + #define CRASH_CHECK_DISK_PATH "/opt/usr" #define WAIT_FOR_OPT_TIMEOUT_SEC 60 @@ -104,6 +109,8 @@ static struct crash_info { char info_path[PATH_MAX]; char core_path[PATH_MAX]; char log_path[PATH_MAX]; + char appid[APPID_MAX]; + char pkgid[PKGNAME_MAX]; #ifdef SYS_ASSERT char sysassert_cs_path[PATH_MAX]; bool have_sysassert_report; @@ -111,6 +118,93 @@ static struct crash_info { int prstatus_fd; } crash_info; +/* pkgmgrinfo filter list function for getting application ID */ +static int appinfo_get_appid_func(pkgmgrinfo_appinfo_h handle, + void *user_data) +{ + char *str = NULL; + int ret = PMINFO_R_ERROR; + + pkgmgrinfo_appinfo_get_appid(handle, &str); + if (str) { + (*(char **)user_data) = strdup(str); + ret = PMINFO_R_OK; + } + return ret; +} + +/* get application ID by pkgmgrinfo filter */ +static int get_appid(char *exepath, char *appid, int len) +{ + pkgmgrinfo_appinfo_filter_h handle = NULL; + int count, ret; + char *aid = NULL; + + ret = pkgmgrinfo_appinfo_filter_create(&handle); + if (ret != PMINFO_R_OK) { + ret = -1; + goto out; + } + + ret = pkgmgrinfo_appinfo_filter_add_string(handle, PMINFO_APPINFO_PROP_APP_EXEC, exepath); + if (ret != PMINFO_R_OK) { + ret = -1; + goto out_free; + } + + ret = pkgmgrinfo_appinfo_filter_count(handle, &count); + if (ret != PMINFO_R_OK) { + ret = -1; + goto out_free; + } + + if (count < 1) { + ret = -1; + goto out_free; + } + + ret = pkgmgrinfo_appinfo_filter_foreach_appinfo(handle, appinfo_get_appid_func, &aid); + if (ret != PMINFO_R_OK) { + ret = -1; + goto out_free; + } + if (aid) { + snprintf(appid, len, "%s", aid); + ret = 0; + free(aid); + } + +out_free: + pkgmgrinfo_appinfo_filter_destroy(handle); +out: + return ret; +} + +/* get package ID by appid */ +static int get_pkgid(char *appid, char *pkgid, int len) +{ + pkgmgrinfo_appinfo_h handle = NULL; + int ret; + char *pkid = NULL; + + ret = pkgmgrinfo_appinfo_get_appinfo(appid, &handle); + if (ret != PMINFO_R_OK) { + ret = -1; + goto out; + } + ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkid); + if (ret != PMINFO_R_OK) { + ret = -1; + goto out_free; + } + snprintf(pkgid, len, "%s", pkid); + +out_free: + pkgmgrinfo_appinfo_destroy_appinfo(handle); +out: + return ret; +} + static void get_config(void) { dictionary *ini = NULL; @@ -415,6 +509,14 @@ static int set_crash_info(int argc, char *argv[]) if (set_prstatus() < 0) goto rm_temp; + if (get_appid(crash_info.cmd_line, crash_info.appid, sizeof(crash_info.appid)) < 0) { + snprintf(crash_info.appid, sizeof(crash_info.appid), "%s", basename(crash_info.cmd_line)); + snprintf(crash_info.pkgid, sizeof(crash_info.pkgid), "%s", basename(crash_info.cmd_line)); + } else { + if (get_pkgid(crash_info.appid, crash_info.pkgid, sizeof(crash_info.pkgid)) < 0) + snprintf(crash_info.pkgid, sizeof(crash_info.pkgid), "%s", crash_info.appid); + } + return 0; rm_temp: @@ -1025,6 +1127,19 @@ int main(int argc, char *argv[]) launch_crash_popup(); #endif + struct NotifyParams notify_params = { + .prstatus_fd = crash_info.prstatus_fd, + .pid = strtol(crash_info.pid_info, NULL, 10), + .tid = strtol(crash_info.tid_info, NULL, 10), + .cmd_name = basename(crash_info.cmd_line), + .cmd_path = crash_info.cmd_path, + .report_path = crash_info.result_path, + .appid = crash_info.appid, + .pkgid = crash_info.pkgid + }; + + send_notify(¬ify_params); + close(crash_info.prstatus_fd); return 0; } diff --git a/src/crash-manager/dbus_notify.c b/src/crash-manager/dbus_notify.c new file mode 100644 index 0000000..6a8c5d8 --- /dev/null +++ b/src/crash-manager/dbus_notify.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Author: Mateusz Moscicki + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include "shared/log.h" +#include "dbus_notify.h" + +#define KERNEL_DEFINED_TASK_COMM_LEN 16 // from include/linux/sched.h + +#define ARM_REG_LR 14 +#define ARM_REG_PC 15 +#define AARCH64_REG_LR 30 + +static int _get_important_registers(int fd, struct RegInfo **reg_info) +{ + int count = -1; + + if (reg_info == NULL) { + _E("reg_info is NULL\n"); + return -1; + } + + *reg_info = NULL; + struct elf_prstatus *prstatus = mmap(NULL, sizeof(struct elf_prstatus), + PROT_READ, MAP_SHARED, fd, 0); + if (prstatus == MAP_FAILED) { + _E("mmap error: %m\n"); + return -1; + } + +#if (defined __i386__) || (defined __x86_64__) + count = 1; +#elif (defined __arm__) || (defined __aarch64__) + count = 2; +#endif + + *reg_info = (struct RegInfo*)malloc(sizeof(struct RegInfo)*count); + struct RegInfo *reginfo = *reg_info; + + if (*reg_info == NULL) { + _E("malloc for reg_info error: %m"); + goto out; + } + +#if (defined __i386__) || (defined __x86_64__) + struct user_regs_struct *g_registers = (struct user_regs_struct*)prstatus->pr_reg; + +#if defined(__i386__) + reginfo[0].name = strdup("x86.eip"); + reginfo[0].value = (long long int)g_registers->eip; +#else + reginfo[0].name = strdup("x86_64.rip"); + reginfo[0].value = (long long int)g_registers->rip; +#endif // defined(__i386__) + + if (reginfo[0].name == NULL) + goto strdup_error; + +#elif defined(__arm__) + + struct user_regs *g_registers; + g_registers = (struct user_regs*)prstatus->pr_reg; + + if ((reginfo[0].name = strdup("arm.pc")) == NULL) + goto strdup_error; + reginfo[0].value = (long long int)g_registers->uregs[ARM_REG_PC]; + if ((reginfo[1].name = strdup("arm.lr")) == NULL) + goto strdup_error; + reginfo[1].value = (long long int)g_registers->uregs[ARM_REG_LR]; + +#elif defined(__aarch64__) + + struct user_regs_struct *g_registers = (struct user_regs_struct*)prstatus->pr_reg; + + if ((reginfo[0].name = strdup("aarch64.pc")) == NULL) + goto strdup_error; + reginfo[0].value = (long long int)g_registers->pc; + if ((reginfo[1].name = strdup("aarch64.lr")) == NULL) + goto strdup_error; + reginfo[1].value = (long long int)g_registers->regs[AARCH64_REG_LR]; + +#endif // (defined __i386__) || (defined __x86_64__) + +out: + if (count <= 0) { + free(*reg_info); + *reg_info = NULL; + } + + munmap(prstatus, sizeof(*prstatus)); + return count; + +strdup_error: + _E("strdup error: %m\n"); + count = -1; + goto out; +} + +static GVariant* build_message_data(const struct NotifyParams *notify_params) +{ + if (notify_params == NULL) + return NULL; + + GVariantBuilder md_builder; + g_variant_builder_init(&md_builder, G_VARIANT_TYPE("(sssssiia{sv})")); + + g_variant_builder_add(&md_builder, "s", notify_params->cmd_name); + g_variant_builder_add(&md_builder, "s", notify_params->cmd_path); + g_variant_builder_add(&md_builder, "s", notify_params->appid); + g_variant_builder_add(&md_builder, "s", notify_params->pkgid); + g_variant_builder_add(&md_builder, "s", notify_params->report_path); + g_variant_builder_add(&md_builder, "i", notify_params->pid); + g_variant_builder_add(&md_builder, "i", notify_params->tid); + + g_variant_builder_open(&md_builder, G_VARIANT_TYPE("a{sv}")); + + struct RegInfo *reg_info; + int regs_count = _get_important_registers(notify_params->prstatus_fd, ®_info); + + /* registers */ + for (int i = 0; i < regs_count; i++) { + g_variant_builder_open(&md_builder, G_VARIANT_TYPE("{sv}")); + + g_variant_builder_add(&md_builder, "s", reg_info[i].name); +#if (defined __x86_64__) || (defined __aarch64__) + g_variant_builder_add(&md_builder, "v", g_variant_new_uint64(reg_info[i].value)); +#else + g_variant_builder_add(&md_builder, "v", g_variant_new_uint32(reg_info[i].value)); +#endif + + free(reg_info[i].name); + g_variant_builder_close(&md_builder); + } + free(reg_info); + + g_variant_builder_close(&md_builder); + + return g_variant_builder_end(&md_builder); +} + +int send_notify(const struct NotifyParams *notify_params) +{ + int result = 1; + + GDBusConnection *conn = NULL; + GError *error = NULL; + + conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (error) { + _E("g_bus_get_sync error: %s\n", error->message); + g_error_free(error); + result = 0; + goto end; + } + + GVariant *data = build_message_data(notify_params); + + if (data == NULL) { + _E("build_message error\n"); + result = 0; + goto end; + } + + g_dbus_connection_emit_signal(conn, + NULL, + CRASH_PATH_CRASH, + CRASH_INTERFACE_CRASH, + PROCESS_CRASHED, + data, + &error); + + if (error) { + _E("g_dbus_connection_emit_signal error: %s\n", error->message); + g_error_free(error); + result = 0; + goto end; + } + + g_dbus_connection_flush_sync(conn, NULL, &error); + if (error) { + _E("g_dbus_connection_flush_sync error: %s\n", error->message); + g_error_free(error); + } +end: + if (conn != NULL) + g_object_unref(conn); + + return result; +} diff --git a/src/crash-manager/dbus_notify.h b/src/crash-manager/dbus_notify.h new file mode 100644 index 0000000..7c2f24d --- /dev/null +++ b/src/crash-manager/dbus_notify.h @@ -0,0 +1,43 @@ +/* + * + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Author: Mateusz Moscicki + */ + +#define CRASH_BUS_NAME "org.tizen.system.crash" +#define CRASH_OBJECT_PATH "/Org/Tizen/System/Crash" +#define CRASH_INTERFACE_NAME CRASH_BUS_NAME +#define CRASH_PATH_CRASH CRASH_OBJECT_PATH"/Crash" +#define CRASH_INTERFACE_CRASH CRASH_INTERFACE_NAME".Crash" +#define PROCESS_CRASHED "ProcessCrashed" + +struct RegInfo { + char *name; + long long int value; +}; + +struct NotifyParams { + int prstatus_fd; + pid_t pid; + pid_t tid; + char *cmd_name; + char *cmd_path; + char *report_path; + char *appid; + char *pkgid; +}; + +int send_notify(const struct NotifyParams *notify_params); -- 2.7.4 From f3624becfce31e2576c0278d2b9007009b0d7396 Mon Sep 17 00:00:00 2001 From: Mateusz Moscicki Date: Thu, 19 Jul 2018 09:42:54 +0200 Subject: [PATCH 05/16] Add ability to set report path in crash-manager.conf To change default report path (/opt/usr/crash/dump/) modify the value in crash-manager.conf: [CrashManager] ... CrashRootPath=/var/crash ... Change-Id: I39b9bc178e989a1aad5727f5becdee74b1e1b13b --- src/crash-manager/crash-manager.c | 137 ++++++++++++++++++++++++++--------- src/crash-manager/crash-manager.conf | 3 + 2 files changed, 106 insertions(+), 34 deletions(-) diff --git a/src/crash-manager/crash-manager.c b/src/crash-manager/crash-manager.c index 2c351fe..2a102c5 100644 --- a/src/crash-manager/crash-manager.c +++ b/src/crash-manager/crash-manager.c @@ -68,7 +68,9 @@ #define APPID_MAX 128 #define PKGNAME_MAX 128 -#define CRASH_CHECK_DISK_PATH "/opt/usr" +#define CRASH_TEMP_SUBDIR "/temp/" +#define CRASH_PATH_SUBDIR "/dump/" + #define WAIT_FOR_OPT_TIMEOUT_SEC 60 #define MINICOREDUMPER_TIMEOUT 12*60 @@ -93,6 +95,9 @@ static int system_keep_free; static int max_retention_sec; static int max_crash_dump; static bool allow_zip; +static char* crash_root_path; +static char* crash_crash_path; +static char* crash_temp_path; /* Paths and variables */ static struct crash_info { @@ -205,22 +210,49 @@ out: return ret; } -static void get_config(void) +static int prepare_paths(void) +{ + int tmp_len; + tmp_len = strlen(crash_root_path) + strlen(CRASH_PATH_SUBDIR); + crash_crash_path = (char*)malloc(tmp_len + 1); + if (crash_crash_path == NULL) { + _E("Couldn't allocate memory for crash_crash_path: %m\n"); + return 0; + } + snprintf(crash_crash_path, tmp_len, "%s%s", crash_root_path, CRASH_PATH_SUBDIR); + + tmp_len = strlen(crash_root_path) + strlen(CRASH_TEMP_SUBDIR); + crash_temp_path = (char*)malloc(tmp_len + 1); + if (crash_temp_path == NULL) { + _E("Couldn't allocate memory for crash_temp_path: %m\n"); + return 0; + } + snprintf(crash_temp_path, tmp_len, "%s%s", crash_root_path, CRASH_TEMP_SUBDIR); + return 1; +} + +static int get_config(void) { dictionary *ini = NULL; char key[KEY_MAX]; int value; + char *value_str; system_max_use = SYSTEM_MAX_USE; system_keep_free = SYSTEM_KEEP_FREE; max_retention_sec = MAX_RETENTION_SEC; max_crash_dump = MAX_CRASH_DUMP; allow_zip = ALLOW_ZIP; + crash_root_path = strdup(CRASH_ROOT_PATH); + if (crash_root_path == NULL) { + _E("strdup error: %m\n"); + return -1; + } ini = iniparser_load(CRASH_CONF_FILE); if (!ini) { - _E("Failed to load conf file"); - return; + _E("Failed to load conf file %s", CRASH_CONF_FILE); + return 0; } snprintf(key, sizeof(key), "%s:%s", CRASH_SECTION, "SystemMaxUse"); @@ -274,33 +306,49 @@ static void get_config(void) allow_zip = value; } + snprintf(key, sizeof(key), "%s:%s", CRASH_SECTION, "CrashRootPath"); + value_str = iniparser_getstring(ini, key, NULL); + if (value_str == NULL) { + _D("Invalid value for CrashRootPath. Use default value [ %s ]", + CRASH_ROOT_PATH); + } else { + _D("CrashRootPath [ %s ]", value_str); + free(crash_root_path); + crash_root_path = strdup(value_str); + if (crash_root_path == NULL) { + _E("strdup error: %m\n"); + return -1; + } + } + iniparser_freedict(ini); + return 1; } static int make_dump_dir(void) { struct stat st; - if (!stat(CRASH_PATH, &st)) { + if (!stat(crash_crash_path, &st)) { if (!(st.st_mode & S_IFDIR)) { - _E("%s (not DIR) is already exist", CRASH_PATH); + _E("%s (not DIR) is already exist", crash_crash_path); return -1; } } else { - if (mkdir(CRASH_PATH, 0775) < 0) { - _E("Failed to mkdir for %s", CRASH_PATH); + if (mkdir(crash_crash_path, 0775) < 0) { + _E("Failed to mkdir for %s", crash_crash_path); return -1; } } - if (!stat(CRASH_TEMP, &st)) { + if (!stat(crash_temp_path, &st)) { if (!(st.st_mode & S_IFDIR)) { - _E("%s (not DIR) is already exist", CRASH_TEMP); + _E("%s (not DIR) is already exist", crash_temp_path); return -1; } } else { - if (mkdir(CRASH_TEMP, 0775) < 0) { - _E("Failed to mkdir for %s", CRASH_TEMP); + if (mkdir(crash_temp_path, 0775) < 0) { + _E("Failed to mkdir for %s", crash_temp_path); return -1; } } @@ -430,7 +478,7 @@ static int set_crash_info(int argc, char *argv[]) "%Y%m%d%H%M%S", &loc_tm); ret = snprintf(crash_info.temp_dir, sizeof(crash_info.temp_dir), - "%s/crash.XXXXXX", CRASH_TEMP); + "%s/crash.XXXXXX", crash_temp_path); if (ret < 0) { _E("Failed to snprintf for temp_dir"); return -1; @@ -453,11 +501,11 @@ static int set_crash_info(int argc, char *argv[]) if (allow_zip) ret = snprintf(crash_info.result_path, sizeof(crash_info.result_path), - "%s/%s.zip", CRASH_PATH, crash_info.name); + "%s/%s.zip", crash_crash_path, crash_info.name); else ret = snprintf(crash_info.result_path, sizeof(crash_info.result_path), - "%s/%s", CRASH_PATH, crash_info.name); + "%s/%s", crash_crash_path, crash_info.name); if (ret < 0) { _E("Failed to snprintf for result path"); goto rm_temp; @@ -768,8 +816,8 @@ static int lock_dumpdir(void) { int fd; - if ((fd = open(CRASH_PATH, O_RDONLY | O_DIRECTORY)) < 0) { - _E("Failed to open %s", CRASH_PATH); + if ((fd = open(crash_crash_path, O_RDONLY | O_DIRECTORY)) < 0) { + _E("Failed to open %s", crash_crash_path); return -1; } @@ -816,12 +864,12 @@ static int scan_dump(struct file_info **dump_list, size_t *usage) int i, scan_num, dump_num = 0; int fd; - if ((fd = open(CRASH_PATH, O_DIRECTORY)) < 0) { - _E("Failed to open %s", CRASH_PATH); + if ((fd = open(crash_crash_path, O_DIRECTORY)) < 0) { + _E("Failed to open %s", crash_crash_path); return -1; } - scan_num = scandir(CRASH_PATH, &scan_list, &dump_filter, NULL); + scan_num = scandir(crash_crash_path, &scan_list, &dump_filter, NULL); if (scan_num < 0) { close(fd); return -1; @@ -841,7 +889,7 @@ static int scan_dump(struct file_info **dump_list, size_t *usage) } if (asprintf(&(temp_list[dump_num].path), "%s/%s", - CRASH_PATH, scan_list[i]->d_name) < 0) { + crash_crash_path, scan_list[i]->d_name) < 0) { _E("Failed to asprintf"); continue; } @@ -988,7 +1036,7 @@ static void clean_dump(void) /* Check disk free space to keep */ if (system_keep_free && - check_disk_available(CRASH_CHECK_DISK_PATH, + check_disk_available(crash_root_path, system_keep_free) < 0) { _I("Disk is not available! so set the maximum number of dump to 1"); max_crash_dump = 1; @@ -1053,14 +1101,14 @@ static int wait_for_opt(unsigned int timeout) { unsigned int count = 0; - while (check_disk_available(CRASH_ROOT_PATH, 0) < 0 && count < timeout) { - log_kmsg("crash-manager: path %s is not available\n", CRASH_ROOT_PATH); + while (check_disk_available(crash_root_path, 0) < 0 && count < timeout) { + log_kmsg("crash-manager: path %s is not available\n", crash_root_path); sleep(1); count++; } if (count >= timeout) { log_kmsg("crash-manager: timeout (%ds) while waiting for %s." - "Probably /opt is not mounted.\n", timeout, CRASH_ROOT_PATH); + "Probably /opt is not mounted.\n", timeout, crash_root_path); return 0; } @@ -1074,6 +1122,7 @@ int main(int argc, char *argv[]) #if defined(TIZEN_ENABLE_COREDUMP) || defined(TIZEN_ENABLE_MINICOREDUMP) int debug_mode = access(DEBUGMODE_PATH, F_OK) == 0; #endif + int res = 0; /* * prctl(PR_SET_DUMPABLE, 0) is not neccessary. Kernel runs the @@ -1081,19 +1130,34 @@ int main(int argc, char *argv[]) * value that prevents from running crash-manager recursively. */ - if (!wait_for_opt(WAIT_FOR_OPT_TIMEOUT_SEC)) - exit(EXIT_FAILURE); - /* Get Configuration */ - get_config(); + if (get_config() < 0) { + res = EXIT_FAILURE; + goto exit; + } + + /* Prepare paths */ + if (!prepare_paths()) { + res = EXIT_FAILURE; + goto exit; + } + + if (!wait_for_opt(WAIT_FOR_OPT_TIMEOUT_SEC)) { + res = EXIT_FAILURE; + goto exit; + } /* Create crash directories */ - if (make_dump_dir() < 0) - exit(EXIT_FAILURE); + if (make_dump_dir() < 0) { + res = EXIT_FAILURE; + goto exit; + } /* Set crash info */ - if (set_crash_info(argc, argv) < 0) - exit(EXIT_FAILURE); + if (set_crash_info(argc, argv) < 0) { + res = EXIT_FAILURE; + goto exit; + } #ifdef SYS_ASSERT /* Fetch callstack of sys-assert */ @@ -1140,6 +1204,11 @@ int main(int argc, char *argv[]) send_notify(¬ify_params); +exit: close(crash_info.prstatus_fd); - return 0; + free(crash_temp_path); + free(crash_root_path); + free(crash_crash_path); + + return res; } diff --git a/src/crash-manager/crash-manager.conf b/src/crash-manager/crash-manager.conf index 9ddac78..08131cc 100644 --- a/src/crash-manager/crash-manager.conf +++ b/src/crash-manager/crash-manager.conf @@ -4,3 +4,6 @@ SystemKeepFree=0 MaxRetentionSec=0 MaxCrashDump=0 AllowZip=yes + +# Crash report path must exist for the reports to be created +# CrashRootPath=/usr/opt/share/crash/ -- 2.7.4 From 3b7eb7087f2106c339972b7ffb0472944a9ceb1b Mon Sep 17 00:00:00 2001 From: Mateusz Moscicki Date: Fri, 20 Jul 2018 12:58:22 +0200 Subject: [PATCH 06/16] Split execute_crash_modules Change-Id: Iae6af748786c68dcb45a50dc37275fe12e40d85d --- src/crash-manager/crash-manager.c | 51 +++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/src/crash-manager/crash-manager.c b/src/crash-manager/crash-manager.c index 2a102c5..80dd82d 100644 --- a/src/crash-manager/crash-manager.c +++ b/src/crash-manager/crash-manager.c @@ -708,16 +708,12 @@ static void save_so_info() get_and_save_so_info(maps_path, so_info_path); } -static void execute_crash_modules(int argc, char *argv[]) +#ifdef TIZEN_ENABLE_COREDUMP +static void execute_crash_pipe(int argc, char *argv[]) { - -#if defined(TIZEN_ENABLE_COREDUMP) || defined(TIZEN_ENABLE_MINICOREDUMP) || defined(TIZEN_FEATURE_PTRACE_CALLSTACK) int ret; char command[PATH_MAX]; -#endif - _D("Execute crash module: "); -#ifdef TIZEN_ENABLE_COREDUMP /* Execute crash-pipe */ ret = snprintf(command, sizeof(command), "%s --save-core %s", @@ -731,10 +727,12 @@ static void execute_crash_modules(int argc, char *argv[]) return; } system_command(command); -#endif - +} +#endif /* TIZEN_ENABLE_COREDUMP */ #ifdef TIZEN_ENABLE_MINICOREDUMP +static void execute_minicoredump(int argc, char *argv[]) +{ char *coredump_name = NULL; char *prstatus_fd_str = NULL; @@ -774,16 +772,15 @@ static void execute_crash_modules(int argc, char *argv[]) free(coredump_name); free(prstatus_fd_str); -#endif +} +#endif /* TIZEN_ENABLE_MINICOREDUMP */ #ifdef TIZEN_FEATURE_PTRACE_CALLSTACK +static void execute_crash_stack(int argc, char *argv[]) +{ + int ret; + char command[PATH_MAX]; -# ifdef SYS_ASSERT - /* Use process_vm_readv() version as fallback if sys-assert - * failed to generate report */ - if (crash_info.have_sysassert_report) - return; -# endif /* Execute crash-stack */ if (argc > 8) ret = snprintf(command, sizeof(command), @@ -809,6 +806,30 @@ static void execute_crash_modules(int argc, char *argv[]) } system_command(command); +} +#endif /* TIZEN_FEATURE_PTRACE_CALLSTACK */ + +static void execute_crash_modules(int argc, char *argv[]) +{ + _D("Execute crash module: "); + +#ifdef TIZEN_ENABLE_COREDUMP + execute_crash_pipe(argc, argv); +#endif + +#ifdef TIZEN_ENABLE_MINICOREDUMP + execute_minicoredump(argc, argv); +#endif + +#ifdef TIZEN_FEATURE_PTRACE_CALLSTACK + +# ifdef SYS_ASSERT + /* Use process_vm_readv() version as fallback if sys-assert + * failed to generate report */ + if (crash_info.have_sysassert_report) + return; +# endif + execute_crash_stack(argc, argv); #endif /* TIZEN_FEATURE_PTRACE_CALLSTACK */ } -- 2.7.4 From 091b5a128c21db104c127c3bd2fb146a0649dad3 Mon Sep 17 00:00:00 2001 From: Mateusz Moscicki Date: Fri, 20 Jul 2018 11:00:49 +0200 Subject: [PATCH 07/16] Add report types Depending on report type we save all zip archive with coredump, logs, so_info and info file, or just only the *.info file. Report type can be set in crash-manager.conf: [CrashManager] ... ReportType=INFO ... Available report types: * INFO - Save *.info file * FULL - Save coredump, *.log, *.so_info and *info file as a ZIP archive (default) Change-Id: I486049ac8eb928ebdc6ac513bdeac3c98aa4adcc --- src/crash-manager/crash-manager.c | 114 ++++++++++++++++++++++++++++++----- src/crash-manager/crash-manager.conf | 3 + 2 files changed, 101 insertions(+), 16 deletions(-) diff --git a/src/crash-manager/crash-manager.c b/src/crash-manager/crash-manager.c index 80dd82d..6ee58f8 100644 --- a/src/crash-manager/crash-manager.c +++ b/src/crash-manager/crash-manager.c @@ -82,6 +82,16 @@ enum { USAGE_EXCEED }; +enum { + REP_TYPE_INFO = 0, + REP_TYPE_FULL +}; + +#define REP_DEFAULT_TYPE REP_TYPE_FULL + +#define REP_TYPE_FULL_STR "FULL" +#define REP_TYPE_INFO_STR "INFO" + struct file_info { bool isdir; int size; @@ -98,6 +108,7 @@ static bool allow_zip; static char* crash_root_path; static char* crash_crash_path; static char* crash_temp_path; +static int report_type; /* Paths and variables */ static struct crash_info { @@ -231,6 +242,33 @@ static int prepare_paths(void) return 1; } +static const char* report_type_to_str(const int report_type) +{ + switch (report_type) { + case REP_TYPE_INFO: + return REP_TYPE_INFO_STR; + break; + case REP_TYPE_FULL: + return REP_TYPE_FULL_STR; + default: + return NULL; + break; + } +} + +static int report_type_from_str(const char* report_type_str) +{ + if (report_type_str == NULL) + return -1; + + if (strncmp(report_type_str, REP_TYPE_FULL_STR, strlen(REP_TYPE_FULL_STR)) == 0) + return REP_TYPE_FULL; + else if (strncmp(report_type_str, REP_TYPE_INFO_STR, strlen(REP_TYPE_INFO_STR)) == 0) + return REP_TYPE_INFO; + + return -1; +} + static int get_config(void) { dictionary *ini = NULL; @@ -248,6 +286,7 @@ static int get_config(void) _E("strdup error: %m\n"); return -1; } + report_type = REP_DEFAULT_TYPE; ini = iniparser_load(CRASH_CONF_FILE); if (!ini) { @@ -321,6 +360,22 @@ static int get_config(void) } } + snprintf(key, sizeof(key), "%s:%s", CRASH_SECTION, "ReportType"); + value_str = iniparser_getstring(ini, key, NULL); + if (value_str == NULL) { + _D("Invalid value for ReportType. Use default value [ %s ]", + report_type_to_str(report_type)); + } else { + _D("ReportType [ %s ]", value_str); + report_type = report_type_from_str(value_str); + + if (report_type < 0) { + _E("Unknown ReportType %s. Fallback to default: %s", + value_str, report_type_to_str(REP_DEFAULT_TYPE)); + report_type = REP_DEFAULT_TYPE; + } + } + iniparser_freedict(ini); return 1; } @@ -814,7 +869,8 @@ static void execute_crash_modules(int argc, char *argv[]) _D("Execute crash module: "); #ifdef TIZEN_ENABLE_COREDUMP - execute_crash_pipe(argc, argv); + if (report_type >= REP_TYPE_FULL) + execute_crash_pipe(argc, argv); #endif #ifdef TIZEN_ENABLE_MINICOREDUMP @@ -1118,6 +1174,27 @@ static void move_dump_dir(void) _E("Failed to delete temp directory"); } +static void move_info_file(void) +{ + int lock_fd; + + if ((lock_fd = lock_dumpdir()) < 0) + return; + + char dest_path[PATH_MAX]; + snprintf(dest_path, sizeof(dest_path), "%s/%s.info", + crash_crash_path, crash_info.name); + if (!rename(crash_info.info_path, dest_path)) + clean_dump(); + else + _E("Failed to move %s to %s", + crash_info.info_path, dest_path); + + unlock_dumpdir(lock_fd); + if (remove_dir(crash_info.temp_dir, 1) < 0) + _E("Failed to delete temp directory"); +} + static int wait_for_opt(unsigned int timeout) { unsigned int count = 0; @@ -1185,27 +1262,32 @@ int main(int argc, char *argv[]) get_sysassert_cs(); #endif - /* Exec dump_systemstate */ - dump_state_pid = dump_system_state(); - - /* Copy maps file to temp dir */ - copy_maps(); + if (report_type >= REP_TYPE_FULL) { + /* Exec dump_systemstate */ + dump_state_pid = dump_system_state(); + /* Copy maps file to temp dir */ + copy_maps(); + } /* Exec crash modules */ execute_crash_modules(argc, argv); - /* Save shared objects info (file names, bulid IDs, rpm package names) */ - save_so_info(); - remove_maps(); + if (report_type >= REP_TYPE_FULL) { + /* Save shared objects info (file names, bulid IDs, rpm package names) */ + save_so_info(); + remove_maps(); - /* Wait dump_system_state */ - wait_system_command(dump_state_pid); + /* Wait dump_system_state */ + wait_system_command(dump_state_pid); - /* Tar compression */ - if (allow_zip) - compress(); - else - move_dump_dir(); + /* Tar compression */ + if (allow_zip) + compress(); + else + move_dump_dir(); + } else { + move_info_file(); + } #if defined(TIZEN_ENABLE_COREDUMP) || defined(TIZEN_ENABLE_MINICOREDUMP) /* launch crash-popup only if the .debugmode file is exist*/ if (debug_mode) diff --git a/src/crash-manager/crash-manager.conf b/src/crash-manager/crash-manager.conf index 08131cc..98e8690 100644 --- a/src/crash-manager/crash-manager.conf +++ b/src/crash-manager/crash-manager.conf @@ -7,3 +7,6 @@ AllowZip=yes # Crash report path must exist for the reports to be created # CrashRootPath=/usr/opt/share/crash/ + +# Report type can be FULL (.zip) or INFO (.info only) +# ReportType=FULL -- 2.7.4 From a1306a01bf4847d4d4555f10af0e58ea85bb6494 Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Wed, 22 Aug 2018 08:50:42 +0200 Subject: [PATCH 08/16] Remove unsupported and misleading configuration options - Remove TIZEN_FEATURE_PTRACE_CALLSTACK option Crash report generation method has been reworked and does not depend on ptrace anymore. - Remove TIZEN_ENABLE_MINICOREDUMPER option Minicoredumper is required to dump PRSTATUS, which is later used by crash-manager (for D-Bus signal) and by crash-stack (for callstack unwinding) - Remove TIZEN_ENABLE_COREDUMP option crash-pipe does not dump PRSTATUS so can not be used as an option (see above). Consequently, enabling/disabling coredumps has been moved to configuration file (DumpCore=0/1). Change-Id: If535acfe7e64fdde0a8b50afd8b3a1f44fda2490 --- CMakeLists.txt | 8 +- packaging/crash-worker.spec | 30 +------ src/crash-manager/CMakeLists.txt | 20 ----- src/crash-manager/crash-manager.c | 75 +++++++--------- src/crash-manager/crash-manager.conf | 4 + src/crash-manager/crash-manager.h.in | 3 - src/crash-pipe/CMakeLists.txt | 7 -- src/crash-pipe/crash-pipe.c | 162 ----------------------------------- 8 files changed, 39 insertions(+), 270 deletions(-) delete mode 100644 src/crash-pipe/CMakeLists.txt delete mode 100644 src/crash-pipe/crash-pipe.c diff --git a/CMakeLists.txt b/CMakeLists.txt index f6e47cb..96ecea7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,13 +10,7 @@ IF("${SYS_ASSERT}" STREQUAL "ON") ADD_SUBDIRECTORY(src/sys-assert) ENDIF("${SYS_ASSERT}" STREQUAL "ON") -IF(TIZEN_ENABLE_COREDUMP STREQUAL on) - ADD_SUBDIRECTORY(src/crash-pipe) -ENDIF() - -IF(TIZEN_FEATURE_PTRACE_CALLSTACK STREQUAL on) - ADD_SUBDIRECTORY(src/crash-stack) -ENDIF() +ADD_SUBDIRECTORY(src/crash-stack) ADD_SUBDIRECTORY(src/dump_systemstate) ADD_SUBDIRECTORY(src/log_dump) diff --git a/packaging/crash-worker.spec b/packaging/crash-worker.spec index 958f558..aebc135 100644 --- a/packaging/crash-worker.spec +++ b/packaging/crash-worker.spec @@ -2,12 +2,12 @@ %define on_off() %{expand:%%{?with_%{1}:ON}%%{!?with_%{1}:OFF}} %define _with_tests on -%define TIZEN_FEATURE_PTRACE_CALLSTACK on -%define TIZEN_FEATURE_MINICOREDUMPER on %bcond_with doc %bcond_with sys_assert %bcond_with tests +# NOTE: To disable coredump set DumpCore=0 in configuration file + Name: crash-worker Summary: Crash-manager Version: 1.2.1 @@ -26,11 +26,9 @@ BuildRequires: cmake BuildRequires: pkgconfig(pkgmgr-info) BuildRequires: pkgconfig(libunwind-generic) -%if "%{TIZEN_FEATURE_PTRACE_CALLSTACK}" == "on" BuildRequires: libelf-devel libelf BuildRequires: libebl-devel libebl BuildRequires: libdw-devel libdw -%endif %if %{with doc} BuildRequires: doxygen @@ -42,13 +40,7 @@ Requires(post): gzip Requires: zip Requires: libelf Requires: libdw - -%if "%{TIZEN_FEATURE_MINICOREDUMPER}" == "on" Requires: %{_sbindir}/minicoredumper -%endif -# If you need support for core dump files (see building below), -# you should add this dependency -# Requires: libebl %description crash-manager @@ -115,21 +107,12 @@ export CFLAGS+=" -Werror" -DCRASH_PATH=%{crash_path} \ -DCRASH_TEMP=%{crash_temp} \ -DDEBUGMODE_PATH=%{debugmode_path} \ -%if "%{TIZEN_FEATURE_MINICOREDUMPER}" == "on" - -DTIZEN_ENABLE_MINICOREDUMP=on \ -DMINICOREDUMPER_PATH=%{_sbindir}/minicoredumper \ -DMINICOREDUMPER_CONF_DIR=%{_sysconfdir}/minicoredumper \ -%else - -DTIZEN_ENABLE_COREDUMP=on \ - -DCRASH_PIPE_PATH=%{_libexecdir}/crash-pipe \ -%endif -%if "%{TIZEN_FEATURE_PTRACE_CALLSTACK}" == "on" -DCRASH_STACK_PATH=%{_libexecdir}/crash-stack \ -%endif -DCRASH_TESTS_PATH=%{_libdir}/crash-worker-tests \ -DSYS_ASSERT=%{on_off sys_assert} \ -DUPGRADE_SCRIPT_PATH=%{upgrade_script_path} \ - -DTIZEN_FEATURE_PTRACE_CALLSTACK=%{TIZEN_FEATURE_PTRACE_CALLSTACK} make %{?jobs:-j%jobs} %if %{with doc} @@ -194,19 +177,12 @@ sed -i "/${pattern}/D" %{_sysconfdir}/ld.so.preload %attr(-,root,root) %{_sysconfdir}/dbus-1/system.d/log_dump.conf %attr(-,root,root) %{_prefix}/lib/sysctl.d/99-crash-manager.conf %attr(-,root,root) %{_datadir}/dbus-1/system-services/org.tizen.system.crash.service - +%{_libexecdir}/crash-stack %if %{with sys_assert} %{_libdir}/libsys-assert.so %{_sysconfdir}/tmpfiles.d/sys-assert.conf %endif -%if "%{TIZEN_FEATURE_MINICOREDUMPER}" != "on" -%{_libexecdir}/crash-pipe -%endif -%if "%{TIZEN_FEATURE_PTRACE_CALLSTACK}" == "on" -%{_libexecdir}/crash-stack -%endif - #upgrade script %attr(-,root,root) %{upgrade_script_path}/500.crash-manager-upgrade.sh diff --git a/src/crash-manager/CMakeLists.txt b/src/crash-manager/CMakeLists.txt index 2b7e6e4..1ad1f93 100644 --- a/src/crash-manager/CMakeLists.txt +++ b/src/crash-manager/CMakeLists.txt @@ -1,18 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6) PROJECT(crash-manager C) -IF(TIZEN_FEATURE_PTRACE_CALLSTACK STREQUAL on) - ADD_DEFINITIONS(-DTIZEN_FEATURE_PTRACE_CALLSTACK) -ENDIF() - -IF(TIZEN_ENABLE_COREDUMP STREQUAL on) - ADD_DEFINITIONS(-DTIZEN_ENABLE_COREDUMP) -ENDIF() - -IF(TIZEN_ENABLE_MINICOREDUMP STREQUAL on) - ADD_DEFINITIONS(-DTIZEN_ENABLE_MINICOREDUMP) -ENDIF() - INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src) SET(CRASH_MANAGER_SRCS crash-manager.c @@ -37,14 +25,6 @@ ENDFOREACH(flag) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIE") -IF(TIZEN_ENABLE_COREDUMP AND TIZEN_ENABLE_MINICOREDUMP) - message(FATAL_ERROR "You can not define TIZEN_ENABLE_COREDUMP and TIZEN_ENABLE_MINICOREDUMP at once.") -ENDIF() - -IF(TIZEN_ENABLE_COREDUMP OR TIZEN_ENABLE_MINICOREDUMP) - OPTION(USE_COREDUMP_CONF "Use COREDUMP CONF" ON) -ENDIF() - CONFIGURE_FILE(crash-manager.h.in crash-manager.h @ONLY) ADD_EXECUTABLE(${PROJECT_NAME} ${CRASH_MANAGER_SRCS}) TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${crash-manager_pkgs_LDFLAGS} -pie -lrt) diff --git a/src/crash-manager/crash-manager.c b/src/crash-manager/crash-manager.c index 6ee58f8..c42f261 100644 --- a/src/crash-manager/crash-manager.c +++ b/src/crash-manager/crash-manager.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -63,6 +64,7 @@ #define SYSTEM_KEEP_FREE 0 #define MAX_RETENTION_SEC 0 #define MAX_CRASH_DUMP 0 +#define DUMP_CORE 1 #define ALLOW_ZIP true #define APPID_MAX 128 @@ -104,6 +106,7 @@ static int system_max_use; static int system_keep_free; static int max_retention_sec; static int max_crash_dump; +static int dump_core; static bool allow_zip; static char* crash_root_path; static char* crash_crash_path; @@ -280,6 +283,7 @@ static int get_config(void) system_keep_free = SYSTEM_KEEP_FREE; max_retention_sec = MAX_RETENTION_SEC; max_crash_dump = MAX_CRASH_DUMP; + dump_core = DUMP_CORE; allow_zip = ALLOW_ZIP; crash_root_path = strdup(CRASH_ROOT_PATH); if (crash_root_path == NULL) { @@ -335,6 +339,16 @@ static int get_config(void) max_crash_dump = value; } + snprintf(key, sizeof(key), "%s:%s", CRASH_SECTION, "DumpCore"); + value = iniparser_getint(ini, key, -1); + if (value != 0 && value != 1) { + _D("Invalid value for DumpCore default value [ %d ]", + DUMP_CORE); + } else { + _D("DumpCore [ %d ]", value); + dump_core = value; + } + snprintf(key, sizeof(key), "%s:%s", CRASH_SECTION, "AllowZip"); value = iniparser_getboolean(ini, key, -1); if (value < 0) { @@ -658,7 +672,6 @@ static int get_sysassert_cs(void) } #endif -#if defined(TIZEN_ENABLE_COREDUMP) || defined(TIZEN_ENABLE_MINICOREDUMP) static void launch_crash_popup(void) { GDBusConnection *conn; @@ -709,7 +722,6 @@ exit: if (parameters) g_variant_unref(parameters); } -#endif static int dump_system_state(void) { @@ -763,29 +775,6 @@ static void save_so_info() get_and_save_so_info(maps_path, so_info_path); } -#ifdef TIZEN_ENABLE_COREDUMP -static void execute_crash_pipe(int argc, char *argv[]) -{ - int ret; - char command[PATH_MAX]; - - /* Execute crash-pipe */ - ret = snprintf(command, sizeof(command), - "%s --save-core %s", - CRASH_PIPE_PATH, - crash_info.core_path); - - _D(" %s", command); - - if (ret < 0) { - _E("Failed to snprintf for crash-pipe command"); - return; - } - system_command(command); -} -#endif /* TIZEN_ENABLE_COREDUMP */ - -#ifdef TIZEN_ENABLE_MINICOREDUMP static void execute_minicoredump(int argc, char *argv[]) { char *coredump_name = NULL; @@ -825,12 +814,25 @@ static void execute_minicoredump(int argc, char *argv[]) run_command_timeout(args[0], args, NULL, MINICOREDUMPER_TIMEOUT); + /* Minicoredumper must be executed to dump at least PRSTATUS for + other tools, coredump, however, might have been disabled. */ + if (!dump_core) { + int ret = -1; + int errno_unlink = 0; + int dirfd = open(crash_info.pfx, O_DIRECTORY); + if (dirfd != -1) { + ret = unlinkat(dirfd, coredump_name, 0); + errno_unlink = errno; + close(dirfd); + } + _D("Saving core disabled - removing coredump %s/%s: %s", crash_info.pfx, coredump_name, + ret == 0 ? "success" : strerror(errno_unlink)); + } + free(coredump_name); free(prstatus_fd_str); } -#endif /* TIZEN_ENABLE_MINICOREDUMP */ -#ifdef TIZEN_FEATURE_PTRACE_CALLSTACK static void execute_crash_stack(int argc, char *argv[]) { int ret; @@ -862,31 +864,20 @@ static void execute_crash_stack(int argc, char *argv[]) system_command(command); } -#endif /* TIZEN_FEATURE_PTRACE_CALLSTACK */ static void execute_crash_modules(int argc, char *argv[]) { _D("Execute crash module: "); -#ifdef TIZEN_ENABLE_COREDUMP - if (report_type >= REP_TYPE_FULL) - execute_crash_pipe(argc, argv); -#endif - -#ifdef TIZEN_ENABLE_MINICOREDUMP execute_minicoredump(argc, argv); -#endif -#ifdef TIZEN_FEATURE_PTRACE_CALLSTACK - -# ifdef SYS_ASSERT +#ifdef SYS_ASSERT /* Use process_vm_readv() version as fallback if sys-assert * failed to generate report */ if (crash_info.have_sysassert_report) return; -# endif +#endif execute_crash_stack(argc, argv); -#endif /* TIZEN_FEATURE_PTRACE_CALLSTACK */ } static int lock_dumpdir(void) @@ -1217,9 +1208,7 @@ int main(int argc, char *argv[]) { /* Execute dump_systemstate in parallel */ static int dump_state_pid; -#if defined(TIZEN_ENABLE_COREDUMP) || defined(TIZEN_ENABLE_MINICOREDUMP) int debug_mode = access(DEBUGMODE_PATH, F_OK) == 0; -#endif int res = 0; /* @@ -1288,11 +1277,9 @@ int main(int argc, char *argv[]) } else { move_info_file(); } -#if defined(TIZEN_ENABLE_COREDUMP) || defined(TIZEN_ENABLE_MINICOREDUMP) /* launch crash-popup only if the .debugmode file is exist*/ if (debug_mode) launch_crash_popup(); -#endif struct NotifyParams notify_params = { .prstatus_fd = crash_info.prstatus_fd, diff --git a/src/crash-manager/crash-manager.conf b/src/crash-manager/crash-manager.conf index 98e8690..82f5b91 100644 --- a/src/crash-manager/crash-manager.conf +++ b/src/crash-manager/crash-manager.conf @@ -10,3 +10,7 @@ AllowZip=yes # Report type can be FULL (.zip) or INFO (.info only) # ReportType=FULL + +# Dump coredump - 1 to enable (default), 0 to disable +# This option applies to ReportType=FULL only! +# DumpCore=1 diff --git a/src/crash-manager/crash-manager.h.in b/src/crash-manager/crash-manager.h.in index 9206737..149a056 100644 --- a/src/crash-manager/crash-manager.h.in +++ b/src/crash-manager/crash-manager.h.in @@ -24,10 +24,7 @@ #define CRASH_ROOT_PATH "@CRASH_ROOT_PATH@" #define CRASH_TEMP "@CRASH_TEMP@" #define SYS_ASSERT "@SYS_ASSERT@" -#ifdef TIZEN_FEATURE_PTRACE_CALLSTACK #define CRASH_STACK_PATH "@CRASH_STACK_PATH@" -#endif -#define CRASH_PIPE_PATH "@CRASH_PIPE_PATH@" #define MINICOREDUMPER_PATH "@MINICOREDUMPER_PATH@" #define MINICOREDUMPER_CONF_DIR "@MINICOREDUMPER_CONF_DIR@" #define DEBUGMODE_PATH "@DEBUGMODE_PATH@" diff --git a/src/crash-pipe/CMakeLists.txt b/src/crash-pipe/CMakeLists.txt deleted file mode 100644 index 3a63f89..0000000 --- a/src/crash-pipe/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -set(CRASH_PIPE_BIN "crash-pipe") -set(CRASH_PIPE_SRCS crash-pipe.c) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -fPIE") -set(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -pie") - -add_executable(${CRASH_PIPE_BIN} ${CRASH_PIPE_SRCS}) -install(TARGETS ${CRASH_PIPE_BIN} DESTINATION libexec) diff --git a/src/crash-pipe/crash-pipe.c b/src/crash-pipe/crash-pipe.c deleted file mode 100644 index 53c0ac0..0000000 --- a/src/crash-pipe/crash-pipe.c +++ /dev/null @@ -1,162 +0,0 @@ -/* crash-pipe: handle core file passed from stdin - * - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the License); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Authors: Karol Lewandowski - * Łukasz Stelmach - */ -#define _GNU_SOURCE 1 - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -enum { - OPT_HELP, - OPT_SAVE_CORE, -}; - -const struct option opts[] = { - { "help", no_argument, 0, OPT_HELP }, - { "save-core", required_argument, 0, OPT_SAVE_CORE }, - { 0, 0, 0, 0 } -}; - -static char *argv0 = ""; - -static void usage(void) -{ - fprintf(stderr, "usage: %s [--help] --save-core FILE_NAME\n", argv0); -} - -static int copy_fd_simple(int in, int out) -{ - static char buf[4096]; - int readb, remaining; - - while ((readb = read(in, buf, sizeof(buf))) > 0) { - int n; - - for (n = 0, remaining = readb ; remaining > 0; remaining -= n) { - n = write(out, buf, remaining); - if (n == -1) - return -errno; - } - } - - return 1; -} - -static int copy_fd_splice(int in, int out) -{ - ssize_t s; - _Bool copied_data = 0; - - ssize_t max_splice = SSIZE_MAX; - - do { - s = splice(in, NULL, out, NULL, max_splice, SPLICE_F_MOVE); - // output file position + len must not exceed the loff_t type limit, - // that's why we reduce len in every iteration - max_splice -= s; - - // We can try to fallback to simple copy only if first splice failed - // (ie. we have not consumed any data yet) - if (!copied_data && s > 0) - copied_data = 1; - - } while (s > 0); - - if (s < 0) - return copied_data ? -errno : 0; - else - return 1; -} - -static int save_core(const char *core_path) -{ - int fd; - int r = 0; - - fd = open(core_path, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); - if (fd == -1) { - syslog(LOG_ERR, "crash-pipe: Unable to save core file to %s: %m\n", core_path); - return -errno; - } - - r = copy_fd_splice(STDIN_FILENO, fd); - if (r == 0) { - lseek(fd, SEEK_SET, 0); - r = copy_fd_simple(STDIN_FILENO, fd); - } - if (r < 0) { - syslog(LOG_ERR, "crash-pipe: Error while saving core file %s: %m. Removing core.\n", core_path); - if (unlink(core_path) < 0) { - // ignore errno because we're already dealing with the one from splice - // amp the log level to CRIT because things are starting to look pretty grim - syslog(LOG_CRIT, "crash-pipe: Error while removing core file %s: %m.\n", core_path); - } - } - - close(fd); - return r; -} - -int main(int argc, char *argv[]) -{ - int c; - char *opt_save_core = NULL; - int ret = 1; - - argv0 = argv[0]; - - while ((c = getopt_long_only(argc, argv, "", opts, NULL)) != -1) { - - if (c == OPT_HELP) { - usage(); - exit(EXIT_SUCCESS); - } else if (c == OPT_SAVE_CORE) { - if (opt_save_core) { - syslog(LOG_WARNING, "crash-pipe: duplicate --save-core passed\n"); - free(opt_save_core); - } - opt_save_core = strdup(optarg); - if (!opt_save_core) { - syslog(LOG_CRIT, "Out of memory. Exiting."); - exit(EXIT_FAILURE); - } - } - } - - argc -= optind; - argv += optind; - - if (opt_save_core) { - ret = save_core(opt_save_core); - free(opt_save_core); - } - - return ret >= 0 ? EXIT_SUCCESS : EXIT_FAILURE; -} -- 2.7.4 From 5270abc897b84ce70ed8925d5c8039aa002b97e9 Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Wed, 22 Aug 2018 09:02:41 +0200 Subject: [PATCH 09/16] Fail early if can not run minicoredumper properly Minicoredumper is essential for gathering report, so it does not make much sense to continue when we can't even pass right parameters (prstatus). Change-Id: Id7560452110871190f243f7ff61f4e849351a8af --- src/crash-manager/crash-manager.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/crash-manager/crash-manager.c b/src/crash-manager/crash-manager.c index c42f261..87b6756 100644 --- a/src/crash-manager/crash-manager.c +++ b/src/crash-manager/crash-manager.c @@ -775,16 +775,18 @@ static void save_so_info() get_and_save_so_info(maps_path, so_info_path); } -static void execute_minicoredump(int argc, char *argv[]) +static int execute_minicoredump(int argc, char *argv[]) { char *coredump_name = NULL; char *prstatus_fd_str = NULL; + int ret = 0; - if (asprintf(&coredump_name, "%s.coredump", crash_info.name) == -1) - coredump_name = strdup("core"); - - if (asprintf(&prstatus_fd_str, "%d", crash_info.prstatus_fd) == -1) - prstatus_fd_str = strdup("-1"); + if (asprintf(&coredump_name, "%s.coredump", crash_info.name) == -1 + || asprintf(&prstatus_fd_str, "%d", crash_info.prstatus_fd) == -1) { + _E("Unable to allocate memory"); + ret = -1; + goto out; + } /* Execute minicoredumper */ char *args[] = { @@ -829,8 +831,11 @@ static void execute_minicoredump(int argc, char *argv[]) ret == 0 ? "success" : strerror(errno_unlink)); } +out: free(coredump_name); free(prstatus_fd_str); + + return ret; } static void execute_crash_stack(int argc, char *argv[]) @@ -865,19 +870,24 @@ static void execute_crash_stack(int argc, char *argv[]) system_command(command); } -static void execute_crash_modules(int argc, char *argv[]) +static int execute_crash_modules(int argc, char *argv[]) { _D("Execute crash module: "); - execute_minicoredump(argc, argv); + if (execute_minicoredump(argc, argv) < 0) { + _E("Failed to run minicoredumper - can not continue"); + return -1; + } #ifdef SYS_ASSERT /* Use process_vm_readv() version as fallback if sys-assert * failed to generate report */ if (crash_info.have_sysassert_report) - return; + return -1; #endif execute_crash_stack(argc, argv); + + return 0; } static int lock_dumpdir(void) @@ -1259,7 +1269,10 @@ int main(int argc, char *argv[]) copy_maps(); } /* Exec crash modules */ - execute_crash_modules(argc, argv); + if (execute_crash_modules(argc, argv) < 0) { + res = EXIT_FAILURE; + goto exit; + } if (report_type >= REP_TYPE_FULL) { /* Save shared objects info (file names, bulid IDs, rpm package names) */ -- 2.7.4 From 885c98b9ea0a2f5084342886eefb29c8198b44a0 Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Wed, 22 Aug 2018 12:28:48 +0200 Subject: [PATCH 10/16] Move crash-manager.conf to /etc This commit brings back config to /etc to avoid problems with config not being available for crashes happening during bootup (when /opt/ is not mounted yet) Change-Id: Ib384f1fd28192dd199565d888c59f0a33d4d578d --- packaging/crash-worker.spec | 3 ++- src/crash-manager/CMakeLists.txt | 2 +- src/crash-manager/crash-manager.c | 5 ++--- src/crash-manager/crash-manager.h.in | 1 + 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packaging/crash-worker.spec b/packaging/crash-worker.spec index aebc135..d19aaf9 100644 --- a/packaging/crash-worker.spec +++ b/packaging/crash-worker.spec @@ -101,6 +101,7 @@ export CFLAGS+=" -Werror" -DTMP_FILES_DIR=%{_sysconfdir}/tmpfiles.d \ -DARCH=%{ARCH} \ -DARCH_BIT=%{ARCH_BIT} \ + -DCRASH_MANAGER_CONFIG_PATH=%{_sysconfdir}/crash-manager.conf \ -DTZ_SYS_ETC=%{TZ_SYS_ETC} \ -DTZ_SYS_BIN=%{TZ_SYS_BIN} \ -DCRASH_ROOT_PATH=%{crash_root_path} \ @@ -173,7 +174,7 @@ sed -i "/${pattern}/D" %{_sysconfdir}/ld.so.preload %{crash_dump_gen}/* %attr(0750,system_fw,system_fw) %{_bindir}/* %{_unitdir}/log_dump.service -%{TZ_SYS_ETC}/crash-manager.conf +%{_sysconfdir}/crash-manager.conf %attr(-,root,root) %{_sysconfdir}/dbus-1/system.d/log_dump.conf %attr(-,root,root) %{_prefix}/lib/sysctl.d/99-crash-manager.conf %attr(-,root,root) %{_datadir}/dbus-1/system-services/org.tizen.system.crash.service diff --git a/src/crash-manager/CMakeLists.txt b/src/crash-manager/CMakeLists.txt index 1ad1f93..ee04dd0 100644 --- a/src/crash-manager/CMakeLists.txt +++ b/src/crash-manager/CMakeLists.txt @@ -43,7 +43,7 @@ ENDIF(USE_COREDUMP_CONF) INSTALL(FILES ${CMAKE_SOURCE_DIR}/src/${PROJECT_NAME}/crash-manager.conf - DESTINATION ${TZ_SYS_ETC} + DESTINATION /etc PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) INSTALL(FILES ${CMAKE_SOURCE_DIR}/src/${PROJECT_NAME}/99-${PROJECT_NAME}.conf diff --git a/src/crash-manager/crash-manager.c b/src/crash-manager/crash-manager.c index 87b6756..96802b3 100644 --- a/src/crash-manager/crash-manager.c +++ b/src/crash-manager/crash-manager.c @@ -47,7 +47,6 @@ #define LOG_TAG "CRASH_MANAGER" /* Parsing */ -#define CRASH_CONF_FILE tzplatform_mkpath(TZ_SYS_ETC, "crash-manager.conf") #define MINICOREDUMPER_CONF_FILE MINICOREDUMPER_CONF_DIR "/minicoredumper.cfg.json" #define KEY_MAX 255 #define CRASH_SECTION "CrashManager" @@ -292,9 +291,9 @@ static int get_config(void) } report_type = REP_DEFAULT_TYPE; - ini = iniparser_load(CRASH_CONF_FILE); + ini = iniparser_load(CRASH_MANAGER_CONFIG_PATH); if (!ini) { - _E("Failed to load conf file %s", CRASH_CONF_FILE); + _E("Failed to load conf file %s", CRASH_MANAGER_CONFIG_PATH); return 0; } diff --git a/src/crash-manager/crash-manager.h.in b/src/crash-manager/crash-manager.h.in index 149a056..dbcd051 100644 --- a/src/crash-manager/crash-manager.h.in +++ b/src/crash-manager/crash-manager.h.in @@ -25,6 +25,7 @@ #define CRASH_TEMP "@CRASH_TEMP@" #define SYS_ASSERT "@SYS_ASSERT@" #define CRASH_STACK_PATH "@CRASH_STACK_PATH@" +#define CRASH_MANAGER_CONFIG_PATH "@CRASH_MANAGER_CONFIG_PATH@" #define MINICOREDUMPER_PATH "@MINICOREDUMPER_PATH@" #define MINICOREDUMPER_CONF_DIR "@MINICOREDUMPER_CONF_DIR@" #define DEBUGMODE_PATH "@DEBUGMODE_PATH@" -- 2.7.4 From 794ec71575854d223ddcd4d355713c43e92b3fa8 Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Wed, 22 Aug 2018 12:30:45 +0200 Subject: [PATCH 11/16] Normalize minicoredumper config variable naming Change-Id: I5669d0d46fc15c8193b5e8ea11d1254838a8dfd1 --- packaging/crash-worker.spec | 4 ++-- src/crash-manager/crash-manager.c | 5 ++--- src/crash-manager/crash-manager.h.in | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/packaging/crash-worker.spec b/packaging/crash-worker.spec index d19aaf9..9aad40e 100644 --- a/packaging/crash-worker.spec +++ b/packaging/crash-worker.spec @@ -108,8 +108,8 @@ export CFLAGS+=" -Werror" -DCRASH_PATH=%{crash_path} \ -DCRASH_TEMP=%{crash_temp} \ -DDEBUGMODE_PATH=%{debugmode_path} \ - -DMINICOREDUMPER_PATH=%{_sbindir}/minicoredumper \ - -DMINICOREDUMPER_CONF_DIR=%{_sysconfdir}/minicoredumper \ + -DMINICOREDUMPER_BIN_PATH=%{_sbindir}/minicoredumper \ + -DMINICOREDUMPER_CONFIG_PATH=%{_sysconfdir}/minicoredumper/minicoredumper.cfg.json \ -DCRASH_STACK_PATH=%{_libexecdir}/crash-stack \ -DCRASH_TESTS_PATH=%{_libdir}/crash-worker-tests \ -DSYS_ASSERT=%{on_off sys_assert} \ diff --git a/src/crash-manager/crash-manager.c b/src/crash-manager/crash-manager.c index 96802b3..b04d7e2 100644 --- a/src/crash-manager/crash-manager.c +++ b/src/crash-manager/crash-manager.c @@ -47,7 +47,6 @@ #define LOG_TAG "CRASH_MANAGER" /* Parsing */ -#define MINICOREDUMPER_CONF_FILE MINICOREDUMPER_CONF_DIR "/minicoredumper.cfg.json" #define KEY_MAX 255 #define CRASH_SECTION "CrashManager" @@ -789,7 +788,7 @@ static int execute_minicoredump(int argc, char *argv[]) /* Execute minicoredumper */ char *args[] = { - MINICOREDUMPER_PATH, // minicoredumper filename path + MINICOREDUMPER_BIN_PATH, // minicoredumper filename path crash_info.pid_info, // %p - pid argv[2], // %u - UID argv[3], // %g - GID @@ -797,7 +796,7 @@ static int execute_minicoredump(int argc, char *argv[]) argv[5], // %t - time of dump "localhost", // %h - hostname "core", // %e - exe name (need for result filename) - MINICOREDUMPER_CONF_FILE, // config file + MINICOREDUMPER_CONFIG_PATH, // config file "-d", crash_info.pfx, // temp dir "-o", diff --git a/src/crash-manager/crash-manager.h.in b/src/crash-manager/crash-manager.h.in index dbcd051..f5a8c4b 100644 --- a/src/crash-manager/crash-manager.h.in +++ b/src/crash-manager/crash-manager.h.in @@ -26,8 +26,8 @@ #define SYS_ASSERT "@SYS_ASSERT@" #define CRASH_STACK_PATH "@CRASH_STACK_PATH@" #define CRASH_MANAGER_CONFIG_PATH "@CRASH_MANAGER_CONFIG_PATH@" -#define MINICOREDUMPER_PATH "@MINICOREDUMPER_PATH@" -#define MINICOREDUMPER_CONF_DIR "@MINICOREDUMPER_CONF_DIR@" +#define MINICOREDUMPER_BIN_PATH "@MINICOREDUMPER_BIN_PATH@" +#define MINICOREDUMPER_CONFIG_PATH "@MINICOREDUMPER_CONFIG_PATH@" #define DEBUGMODE_PATH "@DEBUGMODE_PATH@" #endif -- 2.7.4 From c149659f4aca21cceeae209023463f88fa0c7459 Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Wed, 22 Aug 2018 07:43:14 +0200 Subject: [PATCH 12/16] Release 5.0.1 Major version bump due to versioning scheme change. Major versions will now follow major Tizen releases (eg. crash-worker 5 for Tizen 5). New features: - callstack resolver has been rewritten to not use ptrace This was required to avoid races during resolve process (kernel would wake up ptraced process). Consequently, it's now possible to prepare crash report of VIP process (whose failure causes system to be rebooted). - New-style D-Bus signal ProcessCrashed is now emitted to notify about the crash - .info-only report type now can be selected via configuration option ReportType - Crash dump location can be changed by CrashReportPath config option - Saving core dump (for FULL/.zip reports) can be changed by DumpCore option Change-Id: I91e806d0d516e618802aee7a742120c0281034a1 --- packaging/crash-worker.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/crash-worker.spec b/packaging/crash-worker.spec index 9aad40e..b71789f 100644 --- a/packaging/crash-worker.spec +++ b/packaging/crash-worker.spec @@ -10,7 +10,7 @@ Name: crash-worker Summary: Crash-manager -Version: 1.2.1 +Version: 5.0.1 Release: 1 Group: Framework/system License: Apache-2.0 -- 2.7.4 From eac9b858fdf93ede3b1edcacc49b0792844fce0f Mon Sep 17 00:00:00 2001 From: Mateusz Moscicki Date: Tue, 14 Aug 2018 15:42:02 +0200 Subject: [PATCH 13/16] Move finding TID to crash-manager Additionally find_crash_tid() returns PID for single-threaded applications, instead of -1. Change-Id: Id6fcc652b95bddda954f25cd448f1e090918c231 --- src/crash-manager/crash-manager.c | 49 ++++++++++++++---------- src/crash-stack/crash-stack.c | 78 +-------------------------------------- src/shared/util.c | 78 +++++++++++++++++++++++++++++++++++++++ src/shared/util.h | 2 + 4 files changed, 112 insertions(+), 95 deletions(-) diff --git a/src/crash-manager/crash-manager.c b/src/crash-manager/crash-manager.c index b04d7e2..dd5c0f5 100644 --- a/src/crash-manager/crash-manager.c +++ b/src/crash-manager/crash-manager.c @@ -530,8 +530,26 @@ static int set_crash_info(int argc, char *argv[]) crash_info.pid_info = argv[1]; crash_info.sig_info = argv[4]; - if (argc > 6) - crash_info.tid_info = argv[6]; + if (argc > 6) { + crash_info.tid_info = strdup(argv[6]); + if (crash_info.tid_info == NULL) { + _E("strdup error: %m"); + return -1; + } + } else { + crash_info.tid_info = NULL; + int pid = atoi(crash_info.pid_info); + int tid = find_crash_tid(pid); + if (tid < 0) { + _I("TID not found"); + tid = pid; + } + + if (asprintf(&crash_info.tid_info, "%d", tid) == -1) { + _E("asprintf error: %m"); + return -1; + } + } ret = get_cmd_info(&crash_info); if (ret <= 0) { @@ -842,23 +860,15 @@ static void execute_crash_stack(int argc, char *argv[]) char command[PATH_MAX]; /* Execute crash-stack */ - if (argc > 8) - ret = snprintf(command, sizeof(command), - "%s --pid %s --tid %s --sig %s --prstatus_fd %d > %s", - CRASH_STACK_PATH, - crash_info.pid_info, - crash_info.tid_info, - crash_info.sig_info, - crash_info.prstatus_fd, - crash_info.info_path); - else - ret = snprintf(command, sizeof(command), - "%s --pid %s --sig %s --prstatus_fd %d > %s", - CRASH_STACK_PATH, - crash_info.pid_info, - crash_info.sig_info, - crash_info.prstatus_fd, - crash_info.info_path); + ret = snprintf(command, sizeof(command), + "%s --pid %s --tid %s --sig %s --prstatus_fd %d > %s", + CRASH_STACK_PATH, + crash_info.pid_info, + crash_info.tid_info, + crash_info.sig_info, + crash_info.prstatus_fd, + crash_info.info_path); + _D(" %s", command); if (ret < 0) { _E("Failed to snprintf for crash-stack command"); @@ -1307,6 +1317,7 @@ int main(int argc, char *argv[]) exit: close(crash_info.prstatus_fd); + free(crash_info.tid_info); free(crash_temp_path); free(crash_root_path); free(crash_crash_path); diff --git a/src/crash-stack/crash-stack.c b/src/crash-stack/crash-stack.c index 6a2fca7..c4fdd03 100644 --- a/src/crash-stack/crash-stack.c +++ b/src/crash-stack/crash-stack.c @@ -577,80 +577,6 @@ static void __print_buffer_info(FILE* bufferfile, FILE *outputfile) } /** - * @brief Check wchan of thread - * - * @param pid PID of the inspected process - * @param tid TID of the thread to check - */ -static int check_thread_wchan(int pid, int tid) -{ - int fd, cnt; - char path[PATH_MAX], buf[100]; - - snprintf(path, PATH_MAX, "/proc/%d/task/%d/wchan", pid, tid); - fd = open(path, O_RDONLY); - if (fd == -1) { - _E("open(%s): %s", path, strerror(errno)); - return -errno; - } - cnt = read(fd, buf, sizeof(buf)); - if (cnt == -1 || cnt == sizeof(buf)) { - _E("read(%s): %s", path, strerror(errno)); - close(fd); - return -errno; - } - buf[cnt] = 0; - close(fd); - - if (strncmp("do_coredump", buf, sizeof(buf)) == 0 || strncmp("pipe_wait", buf, sizeof(buf)) == 0) - return tid; - else - return 0; -} - -/** - * @brief Find crashed tid if tid was not offered - * - * @param pid PID of the inspected process - */ -static int find_crash_tid(int pid) -{ - int threadnum = 1; - int crash_tid = -1; - DIR *dir; - struct dirent *entry; - char task_path[PATH_MAX]; - struct stat sb; - - snprintf(task_path, PATH_MAX, "/proc/%d/task", pid); - if (stat(task_path, &sb) == -1) - return -1; - - threadnum = sb.st_nlink - 2; - - if (threadnum > 1) { - dir = opendir(task_path); - if (!dir) { - _E("opendir(%s): %s", task_path, strerror(errno)); - return -1; - } else { - while ((entry = readdir(dir)) != NULL) { - if (strcmp(entry->d_name, ".") == 0 || - strcmp(entry->d_name, "..") == 0) - continue; - crash_tid = check_thread_wchan(pid, - atoi(entry->d_name)); - if (crash_tid > 0) - break; - } - closedir(dir); - return crash_tid; - } - } - return -1; -} - -/** * @brief Main function. * * Main module accepts should be launched with: @@ -700,8 +626,8 @@ int main(int argc, char **argv) if (NULL == outputfile) outputfile = stdout; if (tid == 0) { - if ((tid = find_crash_tid(pid)) < 0) - tid = pid; + fprintf(errfile, "TID not provided\n"); + return errno; } mode_t oldmode = umask(0077); diff --git a/src/shared/util.c b/src/shared/util.c index 21b76d3..3795415 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -739,6 +739,84 @@ int log_kmsg(char *fmt, ...) fclose(file); return result; } + +/** + * @brief Check wchan of thread + * + * @param pid PID of the inspected process + * @param tid TID of the thread to check + */ +static int check_thread_wchan(int pid, int tid) +{ + int fd, cnt; + char path[PATH_MAX], buf[100]; + + snprintf(path, sizeof(path), "/proc/%d/task/%d/wchan", pid, tid); + fd = open(path, O_RDONLY); + if (fd == -1) { + _E("cannot open %s: %m\n", path); + return -errno; + } + cnt = read(fd, buf, sizeof(buf)); + if (cnt == -1 || cnt == sizeof(buf)) { + _E("read %s error: %m\n", path); + close(fd); + return -errno; + } + buf[cnt] = 0; + close(fd); + + if (strncmp("do_coredump", buf, sizeof(buf)) == 0 || strncmp("pipe_wait", buf, sizeof(buf)) == 0) + return tid; + else + return 0; +} + +/** + * @brief Find crashed tid if tid was not offered + * + * @param pid PID of the inspected process + */ +int find_crash_tid(int pid) +{ + int threadnum = 1; + int crash_tid = -1; + DIR *dir; + struct dirent *entry; + char task_path[PATH_MAX]; + struct stat sb; + + snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid); + if (stat(task_path, &sb) == -1) { + _E("no such file: %s", task_path); + return -1; + } + + threadnum = sb.st_nlink - 2; + + if (threadnum > 1) { + dir = opendir(task_path); + if (!dir) { + _E("cannot open %s\n", task_path); + return -1; + } else { + while ((entry = readdir(dir)) != NULL) { + if (strcmp(entry->d_name, ".") == 0 || + strcmp(entry->d_name, "..") == 0) + continue; + crash_tid = check_thread_wchan(pid, + atoi(entry->d_name)); + if (crash_tid > 0) + break; + } + closedir(dir); + return crash_tid; + } + } else if (threadnum == 1) { + return pid; + } + return -1; +} /** * @} */ diff --git a/src/shared/util.h b/src/shared/util.h index a4044e2..301b4e6 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -60,6 +60,8 @@ int validate_env_name(char *name, int len); int validate_file_name(char *name, int len); int log_kmsg(char *fmt, ...); + +int find_crash_tid(int pid); /** * @} */ -- 2.7.4 From e974864a29847f8172323ae44013a3c48e602298 Mon Sep 17 00:00:00 2001 From: Mateusz Moscicki Date: Thu, 23 Aug 2018 12:45:51 +0200 Subject: [PATCH 14/16] Fix report path for INFO report type Change-Id: I973c452cd08a4ac18d4ad7460b21ceb28d9d6364 --- src/crash-manager/crash-manager.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/crash-manager/crash-manager.c b/src/crash-manager/crash-manager.c index dd5c0f5..eaafab9 100644 --- a/src/crash-manager/crash-manager.c +++ b/src/crash-manager/crash-manager.c @@ -1190,14 +1190,13 @@ static void move_info_file(void) if ((lock_fd = lock_dumpdir()) < 0) return; - char dest_path[PATH_MAX]; - snprintf(dest_path, sizeof(dest_path), "%s/%s.info", + snprintf(crash_info.result_path, sizeof(crash_info.result_path), "%s/%s.info", crash_crash_path, crash_info.name); - if (!rename(crash_info.info_path, dest_path)) + if (!rename(crash_info.info_path, crash_info.result_path)) clean_dump(); else _E("Failed to move %s to %s", - crash_info.info_path, dest_path); + crash_info.info_path, crash_info.result_path); unlock_dumpdir(lock_fd); if (remove_dir(crash_info.temp_dir, 1) < 0) -- 2.7.4 From ac2dd9d930046efd17e9e6392cd5dd4a476d25d7 Mon Sep 17 00:00:00 2001 From: Mateusz Moscicki Date: Thu, 23 Aug 2018 13:51:11 +0200 Subject: [PATCH 15/16] Update license information in spec file Change-Id: Iee77a2f8580167eb6e7087465fd820f0fae575a1 --- packaging/crash-worker.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/crash-worker.spec b/packaging/crash-worker.spec index b71789f..c411292 100644 --- a/packaging/crash-worker.spec +++ b/packaging/crash-worker.spec @@ -13,7 +13,7 @@ Summary: Crash-manager Version: 5.0.1 Release: 1 Group: Framework/system -License: Apache-2.0 +License: Apache-2.0 and BSD Source0: %{name}-%{version}.tar.gz Source1001: crash-worker.manifest BuildRequires: pkgconfig(dlog) -- 2.7.4 From 307f57188421fe18a6279b24d6fb70f8d2f72b81 Mon Sep 17 00:00:00 2001 From: Mateusz Moscicki Date: Thu, 23 Aug 2018 13:54:30 +0200 Subject: [PATCH 16/16] Release 5.0.2 Changes from last version: - For INFO report type D-Bus signal has a proper report path - Update license (imported tbstack code is BSD-licensed) - Move finding TID to crash-manager - fixes support on older kernels Change-Id: Ie7e038d4740fcd442e5c599c9d22c91a24c2ce74 --- packaging/crash-worker.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/crash-worker.spec b/packaging/crash-worker.spec index c411292..d695053 100644 --- a/packaging/crash-worker.spec +++ b/packaging/crash-worker.spec @@ -10,7 +10,7 @@ Name: crash-worker Summary: Crash-manager -Version: 5.0.1 +Version: 5.0.2 Release: 1 Group: Framework/system License: Apache-2.0 and BSD -- 2.7.4