summaryrefslogtreecommitdiff
path: root/test/units/testsuite-23.sh
blob: 34899070f1790acb7ec00951ac2c58e67f7989eb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
set -eux
set -o pipefail

: >/failed

declare -i CHILD_PID=0

# Note: all the signal shenanigans are necessary for the Upholds= tests

# Like trap, but passes the signal name as the first argument
trap_with_sig() {
    local fun="${1:?}"
    local sig
    shift

    for sig in "$@"; do
        # shellcheck disable=SC2064
        trap "$fun $sig" "$sig"
    done
}

# Propagate the caught signal to the current child process
handle_signal() {
    local sig="${1:?}"

    if [[ $CHILD_PID -gt 0 ]]; then
        echo "Propagating signal $sig to child process $CHILD_PID"
        kill -s "$sig" "$CHILD_PID"
    fi
}

# In order to make the handle_signal() stuff above work, we have to execute
# each script asynchronously, since bash won't execute traps until the currently
# executed command finishes. This, however, introduces another issue regarding
# how bash's wait works. Quoting:
#
#   When bash is waiting for an asynchronous command via the wait builtin,
#   the reception of a signal for which a trap has been set will cause the wait
#   builtin to return immediately with an exit status greater than 128,
#   immediately after which the trap is executed.
#
# In other words - every time we propagate a signal, wait returns with
# 128+signal, so we have to wait again - repeat until the process dies.
wait_harder() {
    local pid="${1:?}"

    while kill -0 "$pid" &>/dev/null; do
        wait "$pid" || :
    done

    wait "$pid"
}

trap_with_sig handle_signal SIGUSR1 SIGUSR2 SIGRTMIN+1

for script in "${0%.sh}".*.sh; do
    echo "Running $script"
    "./$script" &
    CHILD_PID=$!
    wait_harder "$CHILD_PID"
done

touch /testok
rm /failed