From f71ddbb3fdf30bc8910ad734921d584d0459f7ac Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Wed, 2 Dec 2015 23:21:33 +0100 Subject: [PATCH] Add backtrace support for internal errors --- cmdline/elem.c | 24 +++++++++++------------ cmdline/handle.c | 2 +- cmdline/mingw.c | 23 +++++++++++++++++++++++ cmdline/portable.h | 14 ++++++++++++++ cmdline/rehash.c | 2 +- cmdline/scan.c | 16 ++++++++-------- cmdline/state.c | 40 +++++++++++++++++++-------------------- cmdline/unix.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 9 ++++++++- 9 files changed, 134 insertions(+), 43 deletions(-) diff --git a/cmdline/elem.c b/cmdline/elem.c index 3e7d55cc..c1f8004b 100644 --- a/cmdline/elem.c +++ b/cmdline/elem.c @@ -425,21 +425,21 @@ void file_copy(struct snapraid_file* src_file, struct snapraid_file* dst_file) if (src_file->size != dst_file->size) { /* LCOV_EXCL_START */ log_fatal("Internal inconsistency in copy file with different size\n"); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } if (src_file->mtime_sec != dst_file->mtime_sec) { /* LCOV_EXCL_START */ log_fatal("Internal inconsistency in copy file with different mtime_sec\n"); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } if (src_file->mtime_nsec != dst_file->mtime_nsec) { /* LCOV_EXCL_START */ log_fatal("Internal inconsistency in copy file with different mtime_nsec\n"); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } @@ -489,7 +489,7 @@ int file_block_is_last(struct snapraid_file* file, block_off_t file_pos) if (file_pos >= file->blockmax) { /* LCOV_EXCL_START */ log_fatal("Internal inconsistency in file block position\n"); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } @@ -610,13 +610,13 @@ struct snapraid_chunk* chunk_alloc(block_off_t parity_pos, struct snapraid_file* if (count == 0) { /* LCOV_EXCL_START */ log_fatal("Internal inconsistency when allocating empty chunk for file '%s' at position '%u/%u'\n", file->sub, file_pos, file->blockmax); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } if (file_pos + count > file->blockmax) { /* LCOV_EXCL_START */ log_fatal("Internal inconsistency when allocating overflowing chunk for file '%s' at position '%u:%u/%u'\n", file->sub, file_pos, count, file->blockmax); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } @@ -1162,7 +1162,7 @@ block_off_t fs_file2par_get_ts(struct snapraid_disk* disk, struct snapraid_chunk if (!chunk) { /* LCOV_EXCL_START */ log_fatal("Internal inconsistency when resolving file '%s' at position '%u/%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, disk->name); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } @@ -1184,7 +1184,7 @@ void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snap if (file_pos != chunk->file_pos + chunk->count) { /* LCOV_EXCL_START */ log_fatal("Internal inconsistency when allocating file '%s' at position '%u/%u' in the middle of chunk '%u:%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, chunk->file_pos, chunk->count, disk->name); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } @@ -1205,7 +1205,7 @@ void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snap if (parity_chunk != chunk || file_chunk != chunk) { /* LCOV_EXCL_START */ log_fatal("Internal inconsistency when allocating file '%s' at position '%u/%u' for existing chunk '%u:%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, chunk->file_pos, chunk->count, disk->name); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } @@ -1225,7 +1225,7 @@ void fs_deallocate(struct snapraid_disk* disk, block_off_t parity_pos) if (!chunk) { /* LCOV_EXCL_START */ log_fatal("Internal inconsistency when deallocating parity position '%u' for not existing chunk in disk '%s'\n", parity_pos, disk->name); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } @@ -1274,7 +1274,7 @@ void fs_deallocate(struct snapraid_disk* disk, block_off_t parity_pos) if (parity_chunk != second_chunk || file_chunk != second_chunk) { /* LCOV_EXCL_START */ log_fatal("Internal inconsistency when deallocating parity position '%u' for splitting chunk '%u:%u' in disk '%s'\n", parity_pos, second_chunk->file_pos, second_chunk->count, disk->name); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } @@ -1287,7 +1287,7 @@ struct snapraid_block* fs_file2block_get(struct snapraid_file* file, block_off_t if (file_pos >= file->blockmax) { /* LCOV_EXCL_START */ log_fatal("Internal inconsistency when dereferencing file '%s' at position '%u/%u'\n", file->sub, file_pos, file->blockmax); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } diff --git a/cmdline/handle.c b/cmdline/handle.c index 0f211814..1bc2f86e 100644 --- a/cmdline/handle.c +++ b/cmdline/handle.c @@ -424,7 +424,7 @@ struct snapraid_handle* handle_map(struct snapraid_state* state, unsigned* handl if (k == 0) { /* LCOV_EXCL_START */ log_fatal("Internal error for inconsistent disk mapping.\n"); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } diff --git a/cmdline/mingw.c b/cmdline/mingw.c index acf2e429..dde0b2f5 100644 --- a/cmdline/mingw.c +++ b/cmdline/mingw.c @@ -243,6 +243,29 @@ void os_done(void) FreeLibrary(dll_advapi32); } +void os_abort(void) +{ + void* stack[32]; + size_t size; + unsigned i; + + printf("Stacktrace of " PACKAGE " v" VERSION); + printf(", mingw"); +#ifdef __GNUC__ + printf(", gcc " __VERSION__); +#endif + printf(", %d-bit", (int)sizeof(void *) * 8); + printf("\n"); + + /* get stackstrace, but without symbols */ + size = CaptureStackBackTrace(0, 32, stack, NULL); + + for (i=0; i #endif +#if HAVE_EXECINFO_H +#include +#endif + /** * Disable case check in Windows. */ @@ -322,6 +331,11 @@ void os_init(int opt); */ void os_done(void); +/** + * Abort the process with a stacktrace. + */ +void os_abort(void) __noreturn; + /** * Log file. * diff --git a/cmdline/rehash.c b/cmdline/rehash.c index f62c659d..ec903e16 100644 --- a/cmdline/rehash.c +++ b/cmdline/rehash.c @@ -77,7 +77,7 @@ void state_rehash(struct snapraid_state* state) if (info_get_rehash(info)) { /* LCOV_EXCL_START */ log_fatal("Internal inconsistency for a rehash already in progress\n"); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } diff --git a/cmdline/scan.c b/cmdline/scan.c index 59ff0a78..f525da60 100644 --- a/cmdline/scan.c +++ b/cmdline/scan.c @@ -96,7 +96,7 @@ static void scan_link(struct snapraid_scan* scan, int is_diff, const char* sub, if (link_flag_has(slink, FILE_IS_PRESENT)) { /* LCOV_EXCL_START */ log_fatal("Internal inconsistency for link '%s%s'\n", disk->dir, sub); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } @@ -275,7 +275,7 @@ static void scan_file_deallocate(struct snapraid_scan* scan, struct snapraid_fil if (disk->first_free_block != 0) { /* LCOV_EXCL_START */ log_fatal("Internal inconsistency for first free position at '%u' deallocating file '%s'\n", disk->first_free_block, file->sub); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } @@ -315,7 +315,7 @@ static void scan_file_deallocate(struct snapraid_scan* scan, struct snapraid_fil default : /* LCOV_EXCL_START */ log_fatal("Internal inconsistency in file '%s' deallocating block '%u:%u' state %u\n", file->sub, i, file->blockmax, block_state); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } @@ -654,7 +654,7 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub, if (st->st_nlink <= 1) { /* LCOV_EXCL_START */ log_fatal("Internal inode '%" PRIu64 "' inconsistency for file '%s%s' already present\n", (uint64_t)st->st_ino, disk->dir, sub); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } #endif @@ -722,7 +722,7 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub, if (file_flag_has(file, FILE_IS_PRESENT)) { /* LCOV_EXCL_START */ log_fatal("Internal inode '%" PRIu64 "' inconsistency for files '%s%s' and '%s%s' matching and already present but different\n", file->inode, disk->dir, sub, disk->dir, file->sub); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } @@ -772,7 +772,7 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub, if (file->inode == st->st_ino) { /* LCOV_EXCL_START */ log_fatal("Internal inconsistency in inode '%" PRIu64 "' for files '%s%s' as unexpected matching\n", file->inode, disk->dir, sub); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } } @@ -781,7 +781,7 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub, if (file_flag_has(file, FILE_IS_PRESENT)) { /* LCOV_EXCL_START */ log_fatal("Internal inconsistency in path for file '%s%s' matching and already present\n", disk->dir, sub); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } @@ -1011,7 +1011,7 @@ static void scan_emptydir(struct snapraid_scan* scan, const char* sub) if (dir_flag_has(dir, FILE_IS_PRESENT)) { /* LCOV_EXCL_START */ log_fatal("Internal inconsistency for dir '%s%s'\n", disk->dir, sub); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } diff --git a/cmdline/state.c b/cmdline/state.c index 1353998a..cfb6a888 100644 --- a/cmdline/state.c +++ b/cmdline/state.c @@ -1260,7 +1260,7 @@ static void state_map(struct snapraid_state* state) if (disk == 0) { /* LCOV_EXCL_START */ log_fatal("Internal inconsistency for mapping '%s'\n", map->name); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } @@ -1390,7 +1390,7 @@ void state_refresh(struct snapraid_state* state) if (disk == 0) { /* LCOV_EXCL_START */ log_fatal("Internal inconsistency for mapping '%s'\n", map->name); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } @@ -1670,7 +1670,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S /* LCOV_EXCL_START */ decoding_error(path, f); log_fatal("Internal inconsistency in mapping index!\n"); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } disk = tommy_array_get(&disk_mapping, mapping); @@ -1688,7 +1688,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S /* LCOV_EXCL_START */ decoding_error(path, f); log_fatal("Internal inconsistency in file size too big!\n"); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } @@ -1774,7 +1774,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S /* LCOV_EXCL_START */ decoding_error(path, f); log_fatal("Internal inconsistency in block number!\n"); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } @@ -1782,7 +1782,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S /* LCOV_EXCL_START */ log_fatal("Internal inconsistency in block size %u/%u!\n", blockmax, v_pos + v_count); decoding_error(path, f); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_START */ } @@ -1904,9 +1904,9 @@ static void state_read_content(struct snapraid_state* state, const char* path, S if (v_pos + v_count > blockmax) { /* LCOV_EXCL_START */ - log_fatal("Internal inconsistency in info size %u/%u!\n", blockmax, v_pos + v_count); decoding_error(path, f); - exit(EXIT_FAILURE); + log_fatal("Internal inconsistency in info size %u/%u!\n", blockmax, v_pos + v_count); + os_abort(); /* LCOV_EXCL_STOP */ } @@ -1914,7 +1914,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S if (ret < 0) { /* LCOV_EXCL_START */ decoding_error(path, f); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } @@ -1938,7 +1938,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S /* LCOV_EXCL_START */ decoding_error(path, f); log_fatal("Internal inconsistency for missing previous checksum!\n"); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } @@ -1957,7 +1957,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S /* LCOV_EXCL_START */ decoding_error(path, f); log_fatal("Internal inconsistency for missing info!\n"); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } } else { @@ -1981,7 +1981,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S /* LCOV_EXCL_START */ decoding_error(path, f); log_fatal("Internal inconsistency in mapping index!\n"); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } disk = tommy_array_get(&disk_mapping, mapping); @@ -1996,15 +1996,15 @@ static void state_read_content(struct snapraid_state* state, const char* path, S if (ret < 0) { /* LCOV_EXCL_START */ decoding_error(path, f); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } if (v_pos + v_count > blockmax) { /* LCOV_EXCL_START */ - log_fatal("Internal inconsistency in hole size %u/%u!\n", blockmax, v_pos + v_count); decoding_error(path, f); - exit(EXIT_FAILURE); + log_fatal("Internal inconsistency in hole size %u/%u!\n", blockmax, v_pos + v_count); + os_abort(); /* LCOV_EXCL_STOP */ } @@ -2081,7 +2081,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S /* LCOV_EXCL_START */ decoding_error(path, f); log_fatal("Internal inconsistency in mapping index!\n"); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } disk = tommy_array_get(&disk_mapping, mapping); @@ -2131,7 +2131,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S /* LCOV_EXCL_START */ decoding_error(path, f); log_fatal("Internal inconsistency in mapping index!\n"); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } disk = tommy_array_get(&disk_mapping, mapping); @@ -2180,7 +2180,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S /* LCOV_EXCL_START */ decoding_error(path, f); log_fatal("Internal inconsistency in mapping index!\n"); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } disk = tommy_array_get(&disk_mapping, mapping); @@ -3051,7 +3051,7 @@ static void state_write_content(struct snapraid_state* state, uint32_t* out_crc) if (!disk) { /* LCOV_EXCL_START */ log_fatal("Internal inconsistency for unmapped disk '%s'\n", map->name); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } @@ -3908,7 +3908,7 @@ void state_fscheck(struct snapraid_state* state, const char* ope) if (fs_check(disk) != 0) { /* LCOV_EXCL_START */ log_fatal("Internal inconsistency in filesystem for disk '%s' %s\n", disk->name, ope); - exit(EXIT_FAILURE); + os_abort(); /* LCOV_EXCL_STOP */ } } diff --git a/cmdline/unix.c b/cmdline/unix.c index 9d7ff0d6..7ea37c9e 100644 --- a/cmdline/unix.c +++ b/cmdline/unix.c @@ -1012,5 +1012,52 @@ void os_done(void) { } +void os_abort(void) +{ +#if HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS + void* stack[32]; + char** messages; + size_t size; + unsigned i; + + printf("Stacktrace of " PACKAGE " v" VERSION); +#ifdef _linux + printf(", linux"); +#endif +#ifdef __GNUC__ + printf(", gcc " __VERSION__); +#endif + printf(", %d-bit", (int)sizeof(void *) * 8); + printf("\n"); + + size = backtrace(stack, 32); + + messages = backtrace_symbols(stack, size); + + for (i=1; i