File Index
Files and directories
Sign in
FILE

defer.sh

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/net/lib/sh/defer.sh BASH
  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
~/ Read-only file preview.