diff --git a/src/compiler.h b/src/compiler.h index 86ab76cc..fe36ed3d 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -45,6 +45,8 @@ #else # define attr_warn_unused_result #endif +// An alias for conveninence +#define must_use attr_warn_unused_result #if __has_attribute(nonnull) # define attr_nonnull(...) __attribute__((nonnull(__VA_ARGS__))) diff --git a/src/compton.c b/src/compton.c index 21a5548f..a5fa0075 100644 --- a/src/compton.c +++ b/src/compton.c @@ -28,6 +28,7 @@ #include +#include "err.h" #include "kernel.h" #include "common.h" #include "compiler.h" @@ -2737,6 +2738,10 @@ session_init(int argc, char **argv, Display *dpy, const char *config_file, parse_config(&ps->o, config_file, &shadow_enabled, &fading_enable, &hasneg, winopt_mask); + if (IS_ERR(config_file_to_free)) { + return NULL; + } + // Parse all of the rest command line options get_cfg(&ps->o, argc, argv, shadow_enabled, fading_enable, hasneg, winopt_mask); diff --git a/src/config_libconfig.c b/src/config_libconfig.c index 03ee084f..a7d34131 100644 --- a/src/config_libconfig.c +++ b/src/config_libconfig.c @@ -10,6 +10,7 @@ #include #include +#include "err.h" #include "common.h" #include "compiler.h" #include "config.h" @@ -176,11 +177,11 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad f = open_config_file(config_file, &path); if (!f) { + free(path); if (config_file) { log_fatal("Failed to read configuration file \"%s\".", config_file); - abort(); + return ERR_PTR(-1); } - free(path); return NULL; } @@ -202,11 +203,9 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad fclose(f); f = NULL; if (read_result == CONFIG_FALSE) { - log_error("Error when reading configuration file \"%s\", line %d: %s", + log_fatal("Error when reading configuration file \"%s\", line %d: %s", path, config_error_line(&cfg), config_error_text(&cfg)); - config_destroy(&cfg); - free(path); - return NULL; + goto err; } } config_set_auto_convert(&cfg, 1); @@ -311,7 +310,7 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad opt->vsync = parse_vsync(sval); if (opt->vsync >= NUM_VSYNC) { log_fatal("Cannot parse vsync"); - exit(1); + goto err; } } // --backend @@ -319,7 +318,7 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad opt->backend = parse_backend(sval); if (opt->backend >= NUM_BKEND) { log_fatal("Cannot parse backend"); - exit(1); + goto err; } } // --log-level @@ -382,7 +381,7 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad if (config_lookup_string(&cfg, "blur-kern", &sval) && !parse_conv_kern_lst(sval, opt->blur_kerns, MAX_BLUR_PASS, conv_kern_hasneg)) { log_fatal("Cannot parse \"blur-kern\""); - exit(1); + goto err; } // --resize-damage config_lookup_int(&cfg, "resize-damage", &opt->resize_damage); @@ -395,7 +394,7 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad opt->glx_swap_method = parse_glx_swap_method(sval); if (opt->glx_swap_method == -2) { log_fatal("Cannot parse \"glx-swap-method\""); - exit(1); + goto err; } } // --glx-use-gpushader4 @@ -468,4 +467,9 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad config_destroy(&cfg); return path; + +err: + config_destroy(&cfg); + free(path); + return ERR_PTR(-1); } diff --git a/src/err.h b/src/err.h new file mode 100644 index 00000000..f989bf9c --- /dev/null +++ b/src/err.h @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: MPL-2.0 +// Copyright (c) 2019 Yuxuan Shui + +#pragma once +#include +#include +#include "compiler.h" + +// Functions for error reporting, adopted from Linux + +// INFO in user space we can probably be more liberal about what pointer we consider +// error. e.g. In x86_64 Linux, all addresses with the highest bit set is invalid in user +// space. +#define MAX_ERRNO 4095 + +static inline void *must_use ERR_PTR(intptr_t err) { + return (void *)err; +} + +static inline intptr_t must_use PTR_ERR(void *ptr) { + return (intptr_t)ptr; +} + +static inline bool must_use IS_ERR(void *ptr) { + return unlikely((uintptr_t)ptr > (uintptr_t)-MAX_ERRNO); +} + +static inline bool must_use IS_ERR_OR_NULL(void *ptr) { + return unlikely(!ptr) || IS_ERR(ptr); +} + +static inline intptr_t must_use PTR_ERR_OR_ZERO(void *ptr) { + if (IS_ERR(ptr)) { + return PTR_ERR(ptr); + } + return 0; +}