diff options
author | Mattias Andrée <m@maandree.se> | 2025-03-22 20:42:34 +0100 |
---|---|---|
committer | Mattias Andrée <m@maandree.se> | 2025-03-22 20:42:34 +0100 |
commit | ebd0bdbbf8fbcfc2742a3b62909fe7f761a30890 (patch) | |
tree | 48506648560650c2a527c8b7a09e36fb2e76a078 /src | |
parent | Unlist redshift/issues/807: expected behaviour (diff) | |
download | redshift-ng-ebd0bdbbf8fbcfc2742a3b62909fe7f761a30890.tar.gz redshift-ng-ebd0bdbbf8fbcfc2742a3b62909fe7f761a30890.tar.bz2 redshift-ng-ebd0bdbbf8fbcfc2742a3b62909fe7f761a30890.tar.xz |
Misc stuff
Signed-off-by: Mattias Andrée <m@maandree.se>
Diffstat (limited to 'src')
-rw-r--r-- | src/common.h | 198 | ||||
-rw-r--r-- | src/config-ini.c | 80 | ||||
-rw-r--r-- | src/config.c | 38 | ||||
-rw-r--r-- | src/gamma-coopgamma.c | 10 | ||||
-rw-r--r-- | src/gamma-drm.c | 14 | ||||
-rw-r--r-- | src/gamma-randr.c | 6 | ||||
-rw-r--r-- | src/gamma-w32gdi.c | 2 | ||||
-rw-r--r-- | src/hooks.c | 2 | ||||
-rw-r--r-- | src/redshift.c | 64 | ||||
-rw-r--r-- | src/signals.c | 90 |
10 files changed, 434 insertions, 70 deletions
diff --git a/src/common.h b/src/common.h index cc1852d..e6d62da 100644 --- a/src/common.h +++ b/src/common.h @@ -431,6 +431,85 @@ enum setting_source { /** + * SIGUSR2 signal values as bitmask values + */ +enum signals { + /** + * Block SIGUSR2 until all signals have been processed + */ + SIGNAL_ORDER_BARRIER = 1 << 0, + + /** + * Disable the effects of redshift + */ + SIGNAL_DISABLE = 1 << 1, + + /** + * Enable the effects of redshift + */ + SIGNAL_ENABLE = 1 << 2, + + /** + * Reload the configuration file + * + * Settings from the command line will be overriden + */ + SIGNAL_RELOAD = 1 << 3, + + /** + * Execute into the currently installed version of redshift + */ + SIGNAL_REEXEC = 1 << 4, + + /** + * Set the "fade" setting to off + */ + SIGNAL_USE_FADE_OFF = 1 << 5, + + /** + * Set the "fade" setting to on + */ + SIGNAL_USE_FADE_ON = 1 << 6, + + /** + * Set the "preserve-gamma" setting to off + */ + SIGNAL_PRESERVE_GAMMA_OFF = 1 << 7, + + /** + * Set the "preserve-gamma" setting to on + */ + SIGNAL_PRESERVE_GAMMA_ON = 1 << 8, + + /** + * Exit the process without removing the its effects + * + * If the used adjustment method does not support + * leaving the effects, they will be removed + */ + SIGNAL_EXIT_WITHOUT_RESET = 1 << 9, + + /** + * Do not terminate redshift the standard output + * and standard error are closed + */ + SIGNAL_IGNORE_SIGPIPE = 1 << 10, + + /** + * Enable verbose mode + */ + SIGNAL_VERBOSE_ON = 1 << 11, + + /** + * Disable verbose mode + * + * Ignore if started in verbose mode (-v option) + */ + SIGNAL_VERBOSE_OFF = 1 << 12 +}; + + +/** * Specification for a path that consists of a two parts: * the first being defined by the environment, and the * seocnd being a static string @@ -611,34 +690,79 @@ struct config_ini_state { }; +/** + * `int` valued setting (used for booleans) with setting source + */ struct setting_i { - enum setting_source source; - int value; + enum setting_source source; /**< Setting source */ + int value; /**< Setting value */ }; +/** + * `unsigned long int` valued setting with setting source + */ struct setting_lu { - enum setting_source source; - unsigned long int value; + enum setting_source source; /**< Setting source */ + unsigned long int value; /**< Setting value */ }; +/** + * `double` valued setting with setting source + */ struct setting_f { - enum setting_source source; - double value; + enum setting_source source; /**< Setting source */ + double value; /**< Setting value */ }; +/** + * `double[3]` valued setting with setting source + */ struct setting_f3 { - enum setting_source source; - double value[3]; + enum setting_source source; /**< Setting source */ + double value[3]; /**< Setting values */ }; +/** + * `time_t` valued setting with setting source + */ struct setting_time { - enum setting_source source; - time_t value; + enum setting_source source; /**< Setting source */ + time_t value; /**< Setting value */ }; +/** + * Intermediate settings representation of colour settings + * (for a non-transitional period) with settings sources + * used for determining whether settings from the configuration + * file (which is parsed after the command line) applied or are + * specified multiple times in the configuration file + */ struct setting_colour { + /** + * Colour temperature, in Kelvin + * + * Set by the "-t" and "-o" options and the "temperature" + * ("temp") settings, optionally suffixed "-day" if + * a daytime setting or "-night" if a nighttime setting + */ struct setting_lu temperature; + + /** + * Whitepoint brightness level, as a [0, 1] value + * + * Set by the "-b" option and the "brightness" settings, + * optionally suffixed "-day" if a daytime setting or + * "-night" if a nighttime setting + */ struct setting_f brightness; + + /** + * Gamma values, in the order red, green, blue + * + * Set by the "-g" option and the "gamma" settings, + * optionally suffixed "-day" if a daytime setting or + * "-night" if a nighttime setting + */ struct setting_f3 gamma; }; @@ -705,12 +829,53 @@ struct settings { */ struct setting_colour night; + /** + * The lowest solar elevation, in degrees, at daytime, + * when using solar scheme + * + * This represents the "elevation-high" setting + */ struct setting_f elevation_high; /* TODO no cmdline option */ + + /** + * The highest solar elevation, in degrees, at nighttime, + * when using solar scheme + * + * This represents the "elevation-high" setting + */ struct setting_f elevation_low; /* TODO no cmdline option */ - struct { - struct setting_time start; - struct setting_time end; - } dawn, dusk; /* TODO no cmdline option */ + + /** + * The wall-clock time that marks the end of nighttime, + * when using clock scheme + * + * This represents the left value of the "dawn-time" setting + */ + struct setting_time dawn_start; /* TODO no cmdline option */ + + /** + * The wall-clock time that marks the start of daytime, + * when using clock scheme + * + * This represents the right value of the "dawn-time" setting + */ + struct setting_time dawn_end; /* TODO no cmdline option */ + + /** + * The wall-clock time that marks the end of daytime, + * when using clock scheme + * + * This represents the left value of the "dusk-time" setting + */ + struct setting_time dusk_start; /* TODO no cmdline option */ + + /** + * The wall-clock time that marks the start of nighttime, + * when using clock scheme + * + * This represents the right value of the "dusk-time" setting + */ + struct setting_time dusk_end; /* TODO no cmdline option */ /* Selected gamma method */ const struct gamma_method *method; @@ -956,6 +1121,11 @@ extern volatile sig_atomic_t exiting; extern volatile sig_atomic_t disable; /** + * Bitwise or OR of received SIGUSR2 signal values + */ +extern volatile enum signals signals; + +/** * The colour settings applied at daytime */ extern struct colour_setting day_settings; diff --git a/src/config-ini.c b/src/config-ini.c index 015668f..d5056dc 100644 --- a/src/config-ini.c +++ b/src/config-ini.c @@ -55,23 +55,29 @@ static const struct env_path paths[] = { /** * Open the configuration file for reading * - * @param path The path to the configuration file, or `NULL` if the - * application should look for it in the default paths - * @param path_out Output parameter for the configuration file path - * @param pathbuf_out Output parameter for the memory allocation for `*path_out`; - * will be set to `NULL` unless `path` is `NULL`; shall be - * free(3)d by the caller - * @return `FILE` object for the reading the file; `NULL` if not - * found and `path` is `NULL` + * @param path The path to the configuration file, or `NULL` if the + * application should look for it in the default paths + * @param path_out Output parameter for the configuration file path + * @param pathbuf_out Output parameter for the memory allocation for `*path_out`; + * will be set to `NULL` unless `path` is `NULL`; shall be + * free(3)d by the caller + * @param should_close_out Output parameter for whether the file should be closed + * @return `FILE` object for the reading the file; `NULL` if not + * found and `path` is `NULL` */ static FILE * -open_config_file(const char *path, const char **path_out, char **pathbuf_out) +open_config_file(const char *path, const char **path_out, char **pathbuf_out, int *should_close_out) { FILE *f = NULL; size_t i; +#ifndef WINDOWS + const char *s; + int fd, old_fd = -1; +#endif *path_out = path; *pathbuf_out = NULL; + *should_close_out = 1; if (!path) { for (i = 0; !f && i < ELEMSOF(paths); i++) @@ -80,7 +86,57 @@ open_config_file(const char *path, const char **path_out, char **pathbuf_out) weprintf(_("Found configuration file `%s'."), *path_out); else weprintf(_("No configuration file found.")); + } else if (!strcmp(path, "/dev/null")) { /* needed to allow /dev/null to be specified on Windows */ + return NULL; + } else if (!strcmp(path, "-")) { + *should_close_out = 0; + return stdin; +#ifndef WINDOWS + } else if (!strcmp(path, "/dev/stdin")) { + *should_close_out = 0; + return stdin; + } else if (!strcmp(path, "/dev/stdout")) { + fd = STDOUT_FILENO; + goto use_fd; + } else if (!strcmp(path, "/dev/stderr")) { + fd = STDERR_FILENO; + goto use_fd; + } else if (!strncmp(path, "/dev/fd/", sizeof("/dev/fd/") - 1U)) { + s = &path[sizeof("/dev/fd/") - 1U]; +# if defined(__linux__) + goto parse_fd; + } else if (!strncmp(path, "/proc/self/fd/", sizeof("/proc/self/fd/") - 1U)) { + s = &path[sizeof("/proc/self/fd/") - 1U]; + parse_fd: +# endif + fd = 0; + if (!*s) + goto fallback; + while (isdigit(*s)) { + if (fd > (INT_MAX - (*s & 15)) / 10) + goto fallback; + fd = fd * 10 + (*s & 15); + } + if (*s) + goto fallback; + use_fd: + if (fd > 2) { + fd = dup(old_fd = fd); + if (fd < 0) + eprintf("dup %i:", old_fd); + } + f = fdopen(fd, "r"); + if (!f) { + if (old_fd < 0) + eprintf("fdopen %i \"r\":", fd); + else + eprintf("fdopen <duplicate of %i> \"r\":", old_fd); + } +#endif } else { +#ifndef WINDOWS + fallback: +#endif f = fopen(path, "r"); if (!f) eprintf("fopen %s \"r\":", path); @@ -100,10 +156,11 @@ config_ini_init(struct config_ini_state *state, const char *path) size_t size = 0; ssize_t len = 0; /* initialised to silence false warning from clang */ FILE *f; + int should_close; state->sections = NULL; - f = open_config_file(path, &path, &pathbuf); + f = open_config_file(path, &path, &pathbuf, &should_close); if (!f) return; @@ -172,7 +229,8 @@ again: free(pathbuf); free(line); - fclose(f); + if (should_close) + fclose(f); } diff --git a/src/config.c b/src/config.c index bb6f1d5..751b882 100644 --- a/src/config.c +++ b/src/config.c @@ -27,7 +27,7 @@ static void usage(void) { fprintf(stderr, _("usage: %s %s\n"), argv0, - _("[-b brightness] [-c file] [-D | +D] [-g gamma] " + _("[-b brightness] [-c config-file] [-D | +D] [-g gamma] " "[-l latitude:longitude | -l provider[:options]] " "[-m method[:options]] [-P | +P] [-r | +r] [-dv]" "[-O temperature | -o | -p | -t temperature | -x] " @@ -879,11 +879,11 @@ load_from_config_ini(struct settings *settings, const char *key, char *value) settings->elevation_low.value = checked_atof(value, key); } else if (!strcasecmp(key, "dawn-time")) { - if (!set_transition_time(value, &settings->dawn.start, &settings->dawn.end, key)) + if (!set_transition_time(value, &settings->dawn_start, &settings->dawn_end, key)) eprintf(_("Malformed dawn-time setting `%s'."), value); } else if (!strcasecmp(key, "dusk-time")) { - if (!set_transition_time(value, &settings->dusk.start, &settings->dusk.end, key)) + if (!set_transition_time(value, &settings->dusk_start, &settings->dusk_end, key)) eprintf(_("Malformed dusk-time setting `%s'."), value); } else if (!strcasecmp(key, "adjustment-method")) { @@ -922,28 +922,28 @@ load_settings(struct settings *settings, int argc, char *argv[]) load_from_config_ini(settings, setting->name, setting->value); /* Further validate settings */ - n = !!settings->dawn.start.source + !!settings->dawn.end.source; - n += !!settings->dusk.start.source + !!settings->dusk.end.source; + n = !!settings->dawn_start.source + !!settings->dawn_end.source; + n += !!settings->dusk_start.source + !!settings->dusk_end.source; if (n) { scheme.type = CLOCK_SCHEME; if (n != 4) eprintf(_("Partial time-configuration not supported!")); - if (settings->dawn.start.value >= ONE_DAY || settings->dusk.start.value >= ONE_DAY || - labs((long)settings->dawn.end.value - (long)settings->dawn.start.value) > (long)ONE_DAY || - labs((long)settings->dusk.end.value - (long)settings->dusk.start.value) > (long)ONE_DAY) + if (settings->dawn_start.value >= ONE_DAY || settings->dusk_start.value >= ONE_DAY || + labs((long)settings->dawn_end.value - (long)settings->dawn_start.value) > (long)ONE_DAY || + labs((long)settings->dusk_end.value - (long)settings->dusk_start.value) > (long)ONE_DAY) goto invalid_twilight; /* TODO deal with edge-case where one of the twilights last 24 hour */ - settings->dawn.end.value %= ONE_DAY; - settings->dusk.end.value %= ONE_DAY; - if (settings->dawn.start.value <= settings->dawn.end.value) { - if (BETWEEN(settings->dawn.start.value, settings->dusk.start.value, settings->dawn.end.value) || - BETWEEN(settings->dawn.start.value, settings->dusk.end.value, settings->dawn.end.value)) + settings->dawn_end.value %= ONE_DAY; + settings->dusk_end.value %= ONE_DAY; + if (settings->dawn_start.value <= settings->dawn_end.value) { + if (BETWEEN(settings->dawn_start.value, settings->dusk_start.value, settings->dawn_end.value) || + BETWEEN(settings->dawn_start.value, settings->dusk_end.value, settings->dawn_end.value)) goto invalid_twilight; } else { - if (!WITHIN(settings->dawn.end.value, settings->dusk.start.value, settings->dawn.start.value) || - !WITHIN(settings->dawn.end.value, settings->dusk.end.value, settings->dawn.start.value)) + if (!WITHIN(settings->dawn_end.value, settings->dusk_start.value, settings->dawn_start.value) || + !WITHIN(settings->dawn_end.value, settings->dusk_end.value, settings->dawn_start.value)) goto invalid_twilight; } } @@ -984,13 +984,13 @@ load_settings(struct settings *settings, int argc, char *argv[]) scheme.elevation.range = scheme.elevation.high - scheme.elevation.low; } else if (scheme.type == CLOCK_SCHEME) { scheme.time.periods = &scheme.time.periods_array[0]; - scheme.time.periods_array[0].start = settings->dawn.start.value; + scheme.time.periods_array[0].start = settings->dawn_start.value; scheme.time.periods_array[0].day_level = 0.0; - scheme.time.periods_array[1].start = settings->dawn.end.value; + scheme.time.periods_array[1].start = settings->dawn_end.value; scheme.time.periods_array[1].day_level = 1.0; - scheme.time.periods_array[2].start = settings->dusk.start.value; + scheme.time.periods_array[2].start = settings->dusk_start.value; scheme.time.periods_array[2].day_level = 1.0; - scheme.time.periods_array[3].start = settings->dusk.end.value; + scheme.time.periods_array[3].start = settings->dusk_end.value; scheme.time.periods_array[3].day_level = 0.0; for (i = 0; i < 4; i++) { j = (i + 1) % 4; diff --git a/src/gamma-coopgamma.c b/src/gamma-coopgamma.c index 6f9edb7..5343e08 100644 --- a/src/gamma-coopgamma.c +++ b/src/gamma-coopgamma.c @@ -362,32 +362,28 @@ static void coopgamma_free(struct gamma_state *state) { free(state->methods); - state->methods = NULL; free(state->method); - state->method = NULL; free(state->site); - state->site = NULL; while (state->n_crtcs--) { state->crtcs[state->n_crtcs].filter.class = NULL; libcoopgamma_filter_destroy(&state->crtcs[state->n_crtcs].filter); libcoopgamma_ramps_destroy(&state->crtcs[state->n_crtcs].plain_ramps); } - state->n_crtcs = 0; free(state->crtcs); - state->crtcs = NULL; libcoopgamma_context_destroy(&state->ctx, 1); while (state->n_outputs--) free(state->outputs[state->n_outputs].edid); state->n_outputs = 0; free(state->outputs); - state->outputs = NULL; + + free(state); } static void -coopgamma_print_help(FILE *f) +coopgamma_print_help(FILE *f) /* TODO not documented in readme and manpage */ { fputs(_("Adjust gamma ramps with coopgamma.\n"), f); fputs("\n", f); diff --git a/src/gamma-drm.c b/src/gamma-drm.c index 2098e0d..1713024 100644 --- a/src/gamma-drm.c +++ b/src/gamma-drm.c @@ -221,7 +221,7 @@ drm_print_help(FILE *f) /* TRANSLATORS: DRM help output left column must not be translated */ fputs(_(" card=N\tGraphics card to apply adjustments to\n" - " crtc=N\tCRTC to apply adjustments to\n"), f); + " crtc=N\tCRTC to apply adjustments to\n"), f); /* TODO list is not supported */ fputs("\n", f); } @@ -232,10 +232,14 @@ drm_set_option(struct gamma_state *state, const char *key, const char *value) if (!strcasecmp(key, "card")) { state->card_num = atoi(value); } else if (!strcasecmp(key, "crtc")) { - state->crtc_num = atoi(value); - if (state->crtc_num < 0) { - weprintf(_("CRTC must be a non-negative integer")); - return -1; + if (!strcasecmp(value, "all")) { + state->crtc_num = -1; + } else { + state->crtc_num = atoi(value); + if (state->crtc_num < 0) { + weprintf(_("CRTC must be a non-negative integer")); + return -1; + } } } else { weprintf(_("Unknown method parameter: `%s'."), key); diff --git a/src/gamma-randr.c b/src/gamma-randr.c index 10ea277..9438d17 100644 --- a/src/gamma-randr.c +++ b/src/gamma-randr.c @@ -287,6 +287,12 @@ randr_set_option(struct gamma_state *state, const char *key, const char *value) /* Check how many crtcs are configured */ const char *local_value = value; + if (!*local_value || !strcasecmp(local_value, "all")) { + state->crtc_num_count = 0; + free(state->crtc_num); + state->crtc_num = NULL; + return 0; + } for (;;) { errno = 0; parsed = strtol(local_value, &tail, 0); diff --git a/src/gamma-w32gdi.c b/src/gamma-w32gdi.c index 6912167..6c9f458 100644 --- a/src/gamma-w32gdi.c +++ b/src/gamma-w32gdi.c @@ -198,4 +198,4 @@ done: } -const struct gamma_method w32gdi_gamma_method = GAMMA_METHOD_INIT("winfdi", 1, 0, w32gdi); +const struct gamma_method w32gdi_gamma_method = GAMMA_METHOD_INIT("wingdi", 1, 0, w32gdi); diff --git a/src/hooks.c b/src/hooks.c index 5412582..be02b18 100644 --- a/src/hooks.c +++ b/src/hooks.c @@ -49,7 +49,7 @@ static size_t dirpathlen; /** * Paths, in order of priority, to test when looking for - * the hooks directory for redshift + * the hook directory for redshift */ static const struct env_path paths[] = { {0, "XDG_CONFIG_HOME", "/redshift-ng/hooks"}, diff --git a/src/redshift.c b/src/redshift.c index ddab891..6e9b627 100644 --- a/src/redshift.c +++ b/src/redshift.c @@ -281,7 +281,9 @@ run_continual_mode(void) { enum period period, prev_period = PERIOD_NONE; double day_level = FNAN, prev_day_level = FNAN; - int disabled = 0, prev_disabled = !disabled; + int disabled = disable, prev_disabled = !disable; + int prev_use_fade = !use_fade; + int prev_preserve_gamma = !preserve_gamma; int done = 0; struct colour_setting colour; struct colour_setting target_colour, prev_target_colour; @@ -292,8 +294,15 @@ run_continual_mode(void) double fade_progress, eased_fade_progress; #ifndef WINDOWS int location_fd; + sigset_t sigusr2_mask, old_mask; + enum signals commands; + + sigemptyset(&sigusr2_mask); + sigaddset(&sigusr2_mask, SIGUSR2); #endif + disable = 0; + prev_target_colour = COLOUR_SETTING_NEUTRAL; colour = COLOUR_SETTING_NEUTRAL; @@ -310,9 +319,49 @@ run_continual_mode(void) break; /* On second signal stop the ongoing fade */ done = 1; } - if (verbose && disabled != prev_disabled) - printf(_("Status: %s\n"), disabled ? _("Disabled") : _("Enabled")); +#ifndef WINDOWS + while (signals) { + if (sigprocmask(SIG_BLOCK, &sigusr2_mask, &old_mask)) + eprintf("sigprocmask:"); + commands = signals; + signals = 0; + + if (commands & SIGNAL_ORDER_BARRIER) sigdelset(&old_mask, SIGUSR2); + if (commands & SIGNAL_DISABLE) disabled = 1; + if (commands & SIGNAL_ENABLE) disabled = 0; + if (commands & SIGNAL_RELOAD) {} /* TODO */ + if (commands & SIGNAL_USE_FADE_OFF) use_fade = 0; + if (commands & SIGNAL_USE_FADE_ON) use_fade = 1; + if (commands & SIGNAL_PRESERVE_GAMMA_OFF) preserve_gamma = 0; + if (commands & SIGNAL_PRESERVE_GAMMA_ON) preserve_gamma = 1; + if (commands & SIGNAL_EXIT_WITHOUT_RESET) {} /* TODO */ + if (commands & SIGNAL_VERBOSE_ON) verbose |= 2; + if (commands & SIGNAL_VERBOSE_OFF) verbose &= ~2; + + if (commands & SIGNAL_IGNORE_SIGPIPE) + if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) + weprintf("signal SIGPIPE SIG_IGN:"); + + if (sigprocmask(SIG_SETMASK, &old_mask, NULL)) + eprintf("sigprocmask:"); + +# if defined(__linux__) + if (commands & SIGNAL_REEXEC) { /* TODO */ + } +# endif + } +#endif + if (verbose) { + if (disabled != prev_disabled) + printf(_("Status: %s\n"), disabled ? _("Disabled") : _("Enabled")); + if (use_fade != prev_use_fade) + printf(_("Fade: %s\n"), use_fade ? _("Disabled") : _("Enabled")); + if (preserve_gamma != prev_preserve_gamma) + printf(_("Preserve gamma: %s\n"), use_fade ? _("Disabled") : _("Enabled")); + } prev_disabled = disabled; + prev_use_fade = use_fade; + prev_preserve_gamma = preserve_gamma; /* Get dayness level and corresponding colour settings */ if (disabled) { @@ -462,8 +511,14 @@ main(int argc, char *argv[]) eprintf(_("Temperature adjustment failed.")); if (mode == PROGRAM_MODE_UNTIL_DEATH || method->autoreset) { weprintf(_("Press ctrl-c to stop...")); - while (!exiting) + while (!exiting) { pause(); + if (signals & SIGNAL_EXIT_WITHOUT_RESET) { + /* TODO disable reset if if using coopgamma */ + goto out; + } + } + /* TODO reset if not using coopgamma */ } break; @@ -477,6 +532,7 @@ main(int argc, char *argv[]) #endif } +out: if (provider_state) provider->free(provider_state); if (method_state) diff --git a/src/signals.c b/src/signals.c index 390d684..cd23773 100644 --- a/src/signals.c +++ b/src/signals.c @@ -22,6 +22,7 @@ volatile sig_atomic_t exiting = 0; volatile sig_atomic_t disable = 0; +volatile enum signals signals = 0; /** @@ -40,19 +41,19 @@ sigexit(int signo) } +#ifndef WINDOWS + /** * Signal handler for disable signal (SIGUSR1) * * @param signo The received signal */ -#ifndef WINDOWS static void sigdisable(int signo) { disable = 1; (void) signo; } -#endif /** @@ -61,7 +62,6 @@ sigdisable(int signo) * * @param signo The received signal */ -#ifndef WINDOWS static void sigalrm(int signo) { @@ -70,6 +70,71 @@ sigalrm(int signo) exiting = 1; alarm(1U); } + + +/** + * Signal handler for SIGUSR2 + * + * @param signo The received signal + * @param info The received signal data + * @param uctx Interrupted stack context + */ +static void +sigipc(int signo, siginfo_t *info, void *uctx) +{ + int set, mask; + sigset_t sigusr2_mask; + + (void) signo; + (void) uctx; + + if (info->si_code != SI_QUEUE) + return; + + switch (info->si_value.sival_int) { + case 1: + case 2: + mask = 3 << 1; + break; + + case 5: + case 6: + mask = 3 << 5; + break; + + case 7: + case 8: + mask = 3 << 7; + break; + + case 11: + case 12: + mask = 3 << 11; + break; + + case 0: + case 3: + case 4: + case 9: + case 10: + mask = 0; + break; + + default: + return; + } + + signals |= set = 1 << info->si_value.sival_int; + signals &= ~mask | set; + + if (set == SIGNAL_ORDER_BARRIER) { + sigemptyset(&sigusr2_mask); + sigaddset(&sigusr2_mask, SIGUSR2); + if (sigprocmask(SIG_BLOCK, &sigusr2_mask, NULL)) + eprintf("sigprocmask:"); + } +} + #endif @@ -89,23 +154,32 @@ install_signal_handlers(void) memset(&sigact, 0, sizeof(sigact)); sigemptyset(&sigset); sigact.sa_mask = sigset; - sigact.sa_flags = 0; + + sigact.sa_flags = SA_NODEFER; sigact.sa_handler = &sigexit; if (sigaction(SIGINT, &sigact, NULL)) - eprintf("sigaction SIGINT &{.sa_handler=<function pointer>, .sa_mask={}, .sa_flags=0} NULL:"); + eprintf("sigaction SIGINT &{.sa_handler=<function pointer>, .sa_mask={}, .sa_flags=SA_NODEFER} NULL:"); if (sigaction(SIGTERM, &sigact, NULL)) - eprintf("sigaction SIGTERM &{.sa_handler=<function pointer>, .sa_mask={}, .sa_flags=0} NULL:"); + eprintf("sigaction SIGTERM &{.sa_handler=<function pointer>, .sa_mask={}, .sa_flags=SA_NODEFER} NULL:"); if (sigaction(SIGQUIT, &sigact, NULL)) - eprintf("sigaction SIGQUIT &{.sa_handler=<function pointer>, .sa_mask={}, .sa_flags=0} NULL:"); + eprintf("sigaction SIGQUIT &{.sa_handler=<function pointer>, .sa_mask={}, .sa_flags=SA_NODEFER} NULL:"); sigact.sa_handler = &sigdisable; if (sigaction(SIGUSR1, &sigact, NULL)) - eprintf("sigaction SIGUSR1 &{.sa_handler=<function pointer>, .sa_mask={}, .sa_flags=0} NULL:"); + eprintf("sigaction SIGUSR1 &{.sa_handler=<function pointer>, .sa_mask={}, .sa_flags=SA_NODEFER} NULL:"); + + sigact.sa_flags = 0; sigact.sa_handler = SIG_IGN; /* cause child processes (hooks) to be reaped automatically */ if (sigaction(SIGCHLD, &sigact, NULL)) eprintf("sigaction SIGCHLD &{.sa_handler=SIG_IGN, .sa_mask={}, .sa_flags=0} NULL:"); + + sigact.sa_flags = SA_SIGINFO; + + sigact.sa_sigaction = &sigipc; + if (sigaction(SIGUSR2, &sigact, NULL)) + eprintf("sigaction SIGUSR2 &{.sa_sigaction=<function pointer>, .sa_mask={}, .sa_flags=SA_SIGINFO} NULL:"); #endif } |