linux-sysprog · intermediate · ~15 min

Sigaction Atomic Flag Manager

Implement asynchronous signal flag patterns using volatile sig_atomic_t.

Challenge

POSIX signal handlers cannot execute non-reentrant functions (such as printf or malloc). The canonical Unix pattern sets a volatile sig_atomic_t flag inside the signal handler and handles shutdown logic asynchronously in the main loop.

Your Task

Implement signal flag state management:

#include <signal.h>

void sig_flag_init(void);
void sig_flag_trigger(int signum);
int sig_flag_is_set(void);
int sig_flag_consume(void);

Rules

  1. Maintain a static volatile sig_atomic_t shutdown_requested variable (initialized to 0) and last_signal.
  2. sig_flag_init(): resets shutdown_requested = 0 and last_signal = 0.
  3. sig_flag_trigger(signum): simulates the signal handler: sets shutdown_requested = 1 and last_signal = signum.
  4. sig_flag_is_set(): returns 1 if shutdown_requested is non-zero, or 0 otherwise.
  5. sig_flag_consume(): if shutdown_requested is set, resets shutdown_requested = 0 and returns the last_signal code. If not set, returns 0.

Example

sig_flag_init();
sig_flag_trigger(SIGINT); // e.g. 2
sig_flag_is_set(); // returns 1
sig_flag_consume(); // returns 2
sig_flag_is_set(); // returns 0

Input format

signum: integer signal code (e.g. SIGINT, SIGTERM).

Output format

Returns boolean status or consumed signal number.

Constraints

Must use volatile sig_atomic_t for signal state variables.

Starter code

#include <signal.h>

void sig_flag_init(void) {}
void sig_flag_trigger(int signum) { (void)signum; }
int sig_flag_is_set(void) { return 0; }
int sig_flag_consume(void) { return 0; }

Common mistakes

Using standard int without volatile sig_atomic_t; race conditions in flag checking.

Edge cases to handle

Consuming an un-triggered flag returns 0; multiple triggers preserve latest signal.

Background lessons

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.