File: btest-bg-wait

package info (click to toggle)
btest 0.72-1.1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,208 kB
  • sloc: python: 2,187; sh: 547; makefile: 165; xml: 12; awk: 1
file content (152 lines) | stat: -rwxr-xr-x 3,107 bytes parent folder | download | duplicates (2)
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#! /usr/bin/env bash
#
# Usage: btest-bg-wait [-k] <timeout>
#
# Waits until all of the background process spawned by btest-bg-run
# have finished, or the given timeout (in seconds) has been exceeded.
#
# If the timeout triggers, all remaining processed are killed. If -k
# is not given, this is considered an error and the script abort with
# error code 1. If -k is given, a timeout is not considered an error.
#
# Once all processes have finished (or were killed), the scripts
# merges their stdout and stderr. If one of them returned an error,
# this script does so as well

if [ "$1" == "-k" ]; then
    timeout_ok=1
    shift
else
    timeout_ok=0
fi

if [ $# != 1 ]; then
    echo "usage: $(basename "$0") [-k] <timeout>"
    exit 1
fi

timeout=$1

procs=$(cat .bgprocs)

rm -f .timeout
touch .timeout

function check_procs {
    for p in $procs; do
        if [ ! -e "$p/.exitcode" ]; then
            return 1
        fi
    done

    # All done.
    return 0
}

function kill_procs {
    for p in $procs; do
        if [ ! -e "$p/.exitcode" ]; then
            kill -1 "$(cat "$p/.pid")" 2>/dev/null
            cat "$p"/.cmdline >>.timeout
            if [ "$1" == "timeout" ]; then
                touch "$p/.timeout"
            fi
        fi
    done

    sleep 1

    for p in $procs; do
        if [ ! -e "$p/.exitcode" ]; then
            kill -9 "$(cat "$p/.pid")" 2>/dev/null
            sleep 1
        fi
    done
}

function collect_output {
    rm -f .stdout .stderr

    if [ $timeout_ok != 1 ] && [ -s .timeout ]; then
        {
            echo "The following processes did not terminate:"
            echo

            cat .timeout

            echo
            echo "-----------"
        } >>.stderr
    fi

    for p in $procs; do
        pid=$(cat "$p/.pid")
        cmdline=$(cat "$p/.cmdline")

        {
            printf "<<< [%s] %s\\n" "$pid" "$cmdline"
            cat "$p"/.stdout
            echo ">>>"
        } >>.stdout

        {
            printf "<<< [%s] %s\\n" "$pid" "$cmdline"
            cat "$p"/.stderr
            echo ">>>"
        } >>.stderr
    done
}

trap kill_procs EXIT

while true; do

    if check_procs; then
        # All done.
        break
    fi

    timeout=$((timeout - 1))

    if [ $timeout -le 0 ]; then
        # Timeout exceeded.
        kill_procs timeout

        if [ $timeout_ok == 1 ]; then
            # Just continue.
            break
        fi

        # Exit with error.
        collect_output
        exit 1
    fi

    sleep 1
done

trap - EXIT

# All terminated either by themselves, or with a benign timeout.

collect_output

# See if any returned an error.
result=0
for p in $procs; do
    if [ -e "$p/.timeout" ]; then
        # we're here because timeouts are ok, so don't mind the exit code
        # if we initiated killing the process due to timeout
        continue
    fi
    rc=$(cat "$p/.exitcode")
    pid=$(cat "$p/.pid")
    cmdline=$(cat "$p/.cmdline")

    if [ "$rc" != 0 ]; then
        echo ">>> process $pid failed with exitcode $rc: $cmdline" >>.stderr
        result=1
    fi
done

exit $result