From 752ce69b78bdc34746affa3f32a53c10b5d06285 Mon Sep 17 00:00:00 2001 From: Rob Davies Date: Sun, 16 Dec 2012 10:05:32 +0000 Subject: [PATCH] Added more wrappers for functions that make system calls Added the following wrappers that check the results of system calls and exit non-zero if something went wrong. This is so bwa can be more robust against system failures (e.g. IO errors from remote storage, or running out of memory). The existing and new wrappers have also been modified so that they no longer try to dump core on failure. In most cases the resulting core files are not useful (especially if bwa was compiled with optimization turned on) so just pollute whatever directories they got written to. Wrappers for memory allocation functions: xcalloc xmalloc xrealloc xstrdup New wrappers for IO functions: err_fread_noeof (also dies on EOF) err_gzread err_fseek err_rewind err_ftell --- utils.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++------- utils.h | 29 ++++++++++-- 2 files changed, 143 insertions(+), 20 deletions(-) diff --git a/utils.c b/utils.c index 8c1ad7e..bc39bf5 100644 --- a/utils.c +++ b/utils.c @@ -41,33 +41,44 @@ FILE *err_xopen_core(const char *func, const char *fn, const char *mode) if (strcmp(fn, "-") == 0) return (strstr(mode, "r"))? stdin : stdout; if ((fp = fopen(fn, mode)) == 0) { - fprintf(stderr, "[%s] fail to open file '%s'. Abort!\n", func, fn); - abort(); + err_fatal(func, "fail to open file '%s' : %s", fn, strerror(errno)); } return fp; } FILE *err_xreopen_core(const char *func, const char *fn, const char *mode, FILE *fp) { if (freopen(fn, mode, fp) == 0) { - fprintf(stderr, "[%s] fail to open file '%s': ", func, fn); - perror(NULL); - fprintf(stderr, "Abort!\n"); - abort(); + err_fatal(func, "fail to open file '%s' : %s", fn, strerror(errno)); } return fp; } gzFile err_xzopen_core(const char *func, const char *fn, const char *mode) { gzFile fp; - if (strcmp(fn, "-") == 0) - return gzdopen(fileno((strstr(mode, "r"))? stdin : stdout), mode); + if (strcmp(fn, "-") == 0) { + fp = gzdopen(fileno((strstr(mode, "r"))? stdin : stdout), mode); + /* According to zlib.h, this is the only reason gzdopen can fail */ + if (!fp) err_fatal(func, "Out of memory"); + return fp; + } if ((fp = gzopen(fn, mode)) == 0) { - fprintf(stderr, "[%s] fail to open file '%s'. Abort!\n", func, fn); - abort(); + err_fatal(func, "fail to open file '%s' : %s", fn, errno ? strerror(errno) : "Out of memory"); } return fp; } + void err_fatal(const char *header, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + fprintf(stderr, "[%s] ", header); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); + va_end(args); + exit(EXIT_FAILURE); +} + +void err_fatal_core(const char *header, const char *fmt, ...) { va_list args; va_start(args, fmt); @@ -78,7 +89,13 @@ void err_fatal(const char *header, const char *fmt, ...) abort(); } -void err_fatal_simple_core(const char *func, const char *msg) +void _err_fatal_simple(const char *func, const char *msg) +{ + fprintf(stderr, "[%s] %s\n", func, msg); + exit(EXIT_FAILURE); +} + +void _err_fatal_simple_core(const char *func, const char *msg) { fprintf(stderr, "[%s] %s Abort!\n", func, msg); abort(); @@ -89,11 +106,55 @@ size_t err_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) size_t ret = fwrite(ptr, size, nmemb, stream); if (ret != nmemb) { - err_fatal_simple_core("fwrite", strerror(errno)); + _err_fatal_simple("fwrite", strerror(errno)); } return ret; } +size_t err_fread_noeof(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + size_t ret = fread(ptr, size, nmemb, stream); + if (ret != nmemb) + { + _err_fatal_simple("fread", ferror(stream) ? strerror(errno) : "Unexpected end of file"); + } + return ret; +} + +int err_gzread(gzFile file, void *ptr, unsigned int len) +{ + int ret = gzread(file, ptr, len); + + if (ret < 0) + { + int errnum = 0; + const char *msg = gzerror(file, &errnum); + _err_fatal_simple("gzread", Z_ERRNO == errnum ? strerror(errno) : msg); + } + + return ret; +} + +int err_fseek(FILE *stream, long offset, int whence) +{ + int ret = fseek(stream, offset, whence); + if (0 != ret) + { + _err_fatal_simple("fseek", strerror(errno)); + } + return ret; +} + +long err_ftell(FILE *stream) +{ + long ret = ftell(stream); + if (-1 == ret) + { + _err_fatal_simple("ftell", strerror(errno)); + } + return ret; +} + int err_printf(const char *format, ...) { va_list arg; @@ -106,7 +167,7 @@ int err_printf(const char *format, ...) if (done < 0) { - err_fatal_simple_core("vfprintf(stdout)", strerror(saveErrno)); + _err_fatal_simple("vfprintf(stdout)", strerror(saveErrno)); } return done; } @@ -123,7 +184,7 @@ int err_fprintf(FILE *stream, const char *format, ...) if (done < 0) { - err_fatal_simple_core("vfprintf", strerror(saveErrno)); + _err_fatal_simple("vfprintf", strerror(saveErrno)); } return done; } @@ -133,7 +194,7 @@ int err_fflush(FILE *stream) int ret = fflush(stream); if (ret != 0) { - err_fatal_simple_core("fflush", strerror(errno)); + _err_fatal_simple("fflush", strerror(errno)); } return ret; } @@ -143,11 +204,52 @@ int err_fclose(FILE *stream) int ret = fclose(stream); if (ret != 0) { - err_fatal_simple_core("fclose", strerror(errno)); + _err_fatal_simple("fclose", strerror(errno)); } return ret; } +void *err_calloc(size_t nmemb, size_t size, const char *file, unsigned int line, const char *func) +{ + void *p = calloc(nmemb, size); + if (NULL == p) + { + err_fatal(func, "Failed to allocate %zd bytes at %s line %u: %s\n", nmemb * size, file, line, strerror(errno)); + } + return p; +} + +void *err_malloc(size_t size, const char *file, unsigned int line, const char *func) +{ + void *p = malloc(size); + if (NULL == p) + { + err_fatal(func, "Failed to allocate %zd bytes at %s line %u: %s\n", size, file, line, strerror(errno)); + } + return p; +} + +void *err_realloc(void *ptr, size_t size, const char *file, unsigned int line, const char *func) +{ + void *p = realloc(ptr, size); + if (NULL == p) + { + err_fatal(func, "Failed to allocate %zd bytes at %s line %u: %s\n", size, file, line, strerror(errno)); + } + return p; +} + +char *err_strdup(const char *s, const char *file, unsigned int line, const char *func) +{ + char *p = strdup(s); + + if (NULL == p) + { + err_fatal(func, "Failed to allocate %zd bytes at %s line %u: %s\n", strlen(s), file, line, strerror(errno)); + } + return p; +} + double cputime() { struct rusage r; diff --git a/utils.h b/utils.h index b6839e9..c6cfc81 100644 --- a/utils.h +++ b/utils.h @@ -40,22 +40,38 @@ -#define err_fatal_simple(msg) err_fatal_simple_core(__func__, msg) +#define err_fatal_simple(msg) _err_fatal_simple(__func__, msg) +#define err_fatal_simple_core(msg) _err_fatal_simple_core(__func__, msg) #define xopen(fn, mode) err_xopen_core(__func__, fn, mode) #define xreopen(fn, mode, fp) err_xreopen_core(__func__, fn, mode, fp) #define xzopen(fn, mode) err_xzopen_core(__func__, fn, mode) -#define xassert(cond, msg) if ((cond) == 0) err_fatal_simple_core(__func__, msg) + +#define xassert(cond, msg) if ((cond) == 0) _err_fatal_simple_core(__func__, msg) + +#define xcalloc(n, s) err_calloc( (n), (s), __FILE__, __LINE__, __func__) +#define xmalloc(s) err_malloc( (s), __FILE__, __LINE__, __func__) +#define xrealloc(p, s) err_realloc((p), (s), __FILE__, __LINE__, __func__) +#define xstrdup(s) err_strdup( (s), __FILE__, __LINE__, __func__) + #ifdef __cplusplus extern "C" { #endif - void err_fatal(const char *header, const char *fmt, ...); - void err_fatal_simple_core(const char *func, const char *msg); + void err_fatal(const char *header, const char *fmt, ...) ATTRIBUTE((noreturn)); + void err_fatal_core(const char *header, const char *fmt, ...) ATTRIBUTE((noreturn)); + void _err_fatal_simple(const char *func, const char *msg) ATTRIBUTE((noreturn)); + void _err_fatal_simple_core(const char *func, const char *msg) ATTRIBUTE((noreturn)); FILE *err_xopen_core(const char *func, const char *fn, const char *mode); FILE *err_xreopen_core(const char *func, const char *fn, const char *mode, FILE *fp); gzFile err_xzopen_core(const char *func, const char *fn, const char *mode); size_t err_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); + size_t err_fread_noeof(void *ptr, size_t size, size_t nmemb, FILE *stream); + + int err_gzread(gzFile file, void *ptr, unsigned int len); + int err_fseek(FILE *stream, long offset, int whence); +#define err_rewind(FP) err_fseek((FP), 0, SEEK_SET) + long err_ftell(FILE *stream); int err_fprintf(FILE *stream, const char *format, ...) ATTRIBUTE((format(printf, 2, 3))); int err_printf(const char *format, ...) @@ -63,6 +79,11 @@ extern "C" { int err_fflush(FILE *stream); int err_fclose(FILE *stream); + void *err_calloc(size_t nmemb, size_t size, const char *file, unsigned int line, const char *func); + void *err_malloc(size_t size, const char *file, unsigned int line, const char *func); + void *err_realloc(void *ptr, size_t size, const char *file, unsigned int line, const char *func); + char *err_strdup(const char *s, const char *file, unsigned int line, const char *func); + double cputime(); double realtime();