1#!/bin/sh 2# test program group handling 3 4# Copyright (C) 2011-2023 Free Software Foundation, Inc. 5 6# This program is free software: you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation, either version 3 of the License, or 9# (at your option) any later version. 10 11# This program is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15 16# You should have received a copy of the GNU General Public License 17# along with this program. If not, see <https://www.gnu.org/licenses/>. 18 19. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src 20print_ver_ timeout 21require_trap_signame_ 22require_kill_group_ 23 24# construct a program group hierarchy as follows: 25# timeout-group - foreground group 26# group.sh - separate group 27# timeout.cmd - same group as group.sh 28# 29# We then send a SIGINT to the "separate group" 30# to simulate what happens when a Ctrl-C 31# is sent to the foreground group. 32 33setsid true || skip_ "setsid required to control groups" 34 35printf '%s\n' '#!'"$SHELL" > timeout.cmd || framework_failure_ 36cat >> timeout.cmd <<\EOF 37trap 'touch int.received; exit' INT 38touch timeout.running 39count=$1 40until test -e int.received || test $count = 0; do 41 sleep 1 42 count=$(expr $count - 1) 43done 44EOF 45chmod a+x timeout.cmd 46 47cat > group.sh <<EOF 48#!$SHELL 49trap '' INT 50timeout --foreground 25 ./timeout.cmd 20& 51wait 52EOF 53chmod a+x group.sh 54 55check_timeout_cmd_running() 56{ 57 local delay="$1" 58 test -e timeout.running || 59 { sleep $delay; return 1; } 60} 61 62# Terminate any background processes 63cleanup_() { kill $pid 2>/dev/null && wait $pid; } 64 65# Start above script in its own group. 66# We could use timeout for this, but that assumes an implementation. 67setsid ./group.sh & pid=$! 68# Wait 6.3s for timeout.cmd to start 69retry_delay_ check_timeout_cmd_running .1 6 || fail=1 70# Simulate a Ctrl-C to the group to test timely exit 71kill -INT -- -$pid 72wait 73test -e int.received || fail=1 74 75rm -f int.received timeout.running 76 77 78# Ensure cascaded timeouts work 79# or more generally, ensure we timeout 80# commands that create their own group 81# This didn't work before 8.13. 82 83start=$(date +%s) 84 85# Note the first timeout must send a signal that 86# the second is handling for it to be propagated to the command. 87# SIGINT, SIGTERM, SIGALRM etc. are implicit. 88timeout -sALRM 30 timeout -sINT 25 ./timeout.cmd 20 & pid=$! 89# Wait 6.3s for timeout.cmd to start 90retry_delay_ check_timeout_cmd_running .1 6 || fail=1 91kill -ALRM $pid # trigger the alarm of the first timeout command 92wait $pid 93ret=$? 94test $ret -eq 124 || 95 skip_ "timeout returned $ret. SIGALRM not handled?" 96test -e int.received || fail=1 97 98end=$(date +%s) 99 100test $(expr $end - $start) -lt 20 || 101 skip_ "timeout.cmd didn't receive a signal until after sleep?" 102 103Exit $fail 104