# A12 — debugUnix: sa_mask never initialised via sigemptyset for term/sigpipe handlers

Bug ref      : always.md A.12 ; pharo.md §5.2
Severity     : MEDIUM (uninitialised stack read by kernel; behaviour build-dependent)
File         : src/debugUnix.c
Lines (HEAD) : 122-162 (`installErrorHandlers`)

## Problem

`sigsegv_handler_action` and `sigusr1_handler_action` both have their
`sa_mask` zeroed via `sigemptyset` before being passed to
`sigaction`. `term_handler_action` and `sigpipe_handler_action` do
not:

```c
term_handler_action.sa_sigaction = (void (*)(int, siginfo_t *, void *))terminateHandler;
term_handler_action.sa_flags = SA_NODEFER | SA_SIGINFO;
/* no sigemptyset(&term_handler_action.sa_mask); */

sigaction(SIGHUP, &term_handler_action, 0);
...

sigpipe_handler_action.sa_sigaction = (void (*)(int, siginfo_t *, void *))SIG_IGN;
sigpipe_handler_action.sa_flags = SA_NODEFER | SA_SIGINFO;
/* no sigemptyset(&sigpipe_handler_action.sa_mask); */
```

The two structs live on the stack and the `sa_mask` field is
uninitialised. The kernel uses it to compute which signals to mask
during the handler. Behaviour is undefined and varies between builds,
compilers, and stack layouts.

## Fix

Initialise both masks explicitly.

```diff
--- a/src/unix/debugUnix.c
+++ b/src/unix/debugUnix.c
@@ -141,6 +141,7 @@ EXPORT(void) installErrorHandlers(){
 
 	term_handler_action.sa_sigaction = (void (*)(int, siginfo_t *, void *))terminateHandler;
 	term_handler_action.sa_flags = SA_NODEFER | SA_SIGINFO;
+	sigemptyset(&term_handler_action.sa_mask);
 
 	sigaction(SIGHUP, &term_handler_action, 0);
 	sigaction(SIGTERM, &term_handler_action, 0);
@@ -151,6 +152,7 @@ EXPORT(void) installErrorHandlers(){
 	//Otherwise SIGPIPE kill the process without allowing any recovery or treatment
 	sigpipe_handler_action.sa_sigaction = (void (*)(int, siginfo_t *, void *))SIG_IGN;
 	sigpipe_handler_action.sa_flags = SA_NODEFER | SA_SIGINFO;
+	sigemptyset(&sigpipe_handler_action.sa_mask);
 	sigaction(SIGPIPE, &sigpipe_handler_action, 0);
 	
 	sigusr1_handler_action.sa_sigaction = (void (*)(int, siginfo_t *, void *))sigusr1;

```

## Test plan

- Run `installErrorHandlers` under Valgrind's MemCheck: before,
  Valgrind reports "Conditional jump or move depends on
  uninitialised value(s)" from inside `sigaction`'s argument parse;
  after, clean.
- Verify SIGHUP/SIGTERM still trigger the existing termination
  handler.

## Risk notes

- Strictly safer: explicitly clearing the mask matches what the
  existing `sigsegv_handler_action` / `sigusr1_handler_action` paths
  already do.
- No behavioural change on platforms where the stack happened to be
  zeroed by chance; meaningful difference only on platforms where
  the stack contained set bits that the kernel was interpreting as
  "mask these signals during the handler".
