Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4# Whether to pause and allow debugging when an executed deferred command has a
5# non-zero exit code.
6: "${DEFER_PAUSE_ON_FAIL:=no}"
7
8# map[(scope_id,track,cleanup_id) -> cleanup_command]
9# track={d=default | p=priority}
10declare -A __DEFER__JOBS
11
12# map[(scope_id,track) -> # cleanup_commands]
13declare -A __DEFER__NJOBS
14
15# scope_id of the topmost scope.
16__DEFER__SCOPE_ID=0
17
18__defer__ndefer_key()
19{
20 local track=$1; shift
21
22 echo $__DEFER__SCOPE_ID,$track
23}
24
25__defer__defer_key()
26{
27 local track=$1; shift
28 local defer_ix=$1; shift
29
30 echo $__DEFER__SCOPE_ID,$track,$defer_ix
31}
32
33__defer__ndefers()
34{
35 local track=$1; shift
36
37 echo ${__DEFER__NJOBS[$(__defer__ndefer_key $track)]}
38}
39
40__defer__run()
41{
42 local track=$1; shift
43 local defer_ix=$1; shift
44 local defer_key=$(__defer__defer_key $track $defer_ix)
45 local ret
46
47 eval ${__DEFER__JOBS[$defer_key]}
48 ret=$?
49
50 if [[ "$DEFER_PAUSE_ON_FAIL" == yes && "$ret" -ne 0 ]]; then
51 echo "Deferred command (track $track index $defer_ix):"
52 echo " ${__DEFER__JOBS[$defer_key]}"
53 echo "... ended with an exit status of $ret"
54 echo "Hit enter to continue, 'q' to quit"
55 read a
56 [[ "$a" == q ]] && exit 1
57 fi
58
59 unset __DEFER__JOBS[$defer_key]
60}
61
62__defer__schedule()
63{
64 local track=$1; shift
65 local ndefers=$(__defer__ndefers $track)
66 local ndefers_key=$(__defer__ndefer_key $track)
67 local defer_key=$(__defer__defer_key $track $ndefers)
68 local defer="${@@Q}"
69
70 __DEFER__JOBS[$defer_key]="$defer"
71 __DEFER__NJOBS[$ndefers_key]=$((ndefers + 1))
72}
73
74__defer__scope_wipe()
75{
76 __DEFER__NJOBS[$(__defer__ndefer_key d)]=0
77 __DEFER__NJOBS[$(__defer__ndefer_key p)]=0
78}
79
80defer_scope_push()
81{
82 ((__DEFER__SCOPE_ID++))
83 __defer__scope_wipe
84}
85
86defer_scope_pop()
87{
88 local defer_ix
89
90 for ((defer_ix=$(__defer__ndefers p); defer_ix-->0; )); do
91 __defer__run p $defer_ix
92 done
93
94 for ((defer_ix=$(__defer__ndefers d); defer_ix-->0; )); do
95 __defer__run d $defer_ix
96 done
97
98 __defer__scope_wipe
99 ((__DEFER__SCOPE_ID--))
100}
101
102defer()
103{
104 __defer__schedule d "$@"
105}
106
107defer_prio()
108{
109 __defer__schedule p "$@"
110}
111
112defer_scopes_cleanup()
113{
114 while ((__DEFER__SCOPE_ID >= 0)); do
115 defer_scope_pop
116 done
117}
118
119in_defer_scope()
120{
121 local ret
122
123 defer_scope_push
124 "$@"
125 ret=$?
126 defer_scope_pop
127
128 return $ret
129}
130
131__defer__scope_wipe