1*2abb3134SXin Li#!/bin/bash 2*2abb3134SXin Li# 3*2abb3134SXin Li# Alarm tool. 4*2abb3134SXin Li# 5*2abb3134SXin Li# Usage: 6*2abb3134SXin Li# ./alarm.sh <function name> 7*2abb3134SXin Li 8*2abb3134SXin Li# You can source this file and use the alarm-status function. 9*2abb3134SXin Li 10*2abb3134SXin Liset -o nounset 11*2abb3134SXin Liset -o pipefail 12*2abb3134SXin Liset -o errexit 13*2abb3134SXin Li 14*2abb3134SXin Li# Run a command with a timeout, and print its status to a directory. 15*2abb3134SXin Li# 16*2abb3134SXin Li# Usage: 17*2abb3134SXin Li# alarm-status job_dir/STATUS 10 \ 18*2abb3134SXin Li# flaky_command ... 19*2abb3134SXin Li 20*2abb3134SXin Lialarm-status() { 21*2abb3134SXin Li set +o errexit 22*2abb3134SXin Li local status_file=$1 23*2abb3134SXin Li shift # everything except the status file goes to perl 24*2abb3134SXin Li 25*2abb3134SXin Li # NOTE: It would be nice to setpgrp() before exec? And then can the signal 26*2abb3134SXin Li # be delivered to the entire group, like kill -SIGALRM -PID? 27*2abb3134SXin Li 28*2abb3134SXin Li # NOTE: If we did this in Python, the error message would also be clearer. 29*2abb3134SXin Li perl -e 'alarm shift; exec @ARGV or die "ERROR: after exec @ARGV"' "$@" 30*2abb3134SXin Li local exit_code=$? 31*2abb3134SXin Li 32*2abb3134SXin Li set -o errexit 33*2abb3134SXin Li 34*2abb3134SXin Li local result='' 35*2abb3134SXin Li case $exit_code in 36*2abb3134SXin Li 0) 37*2abb3134SXin Li # Would be nice to show elapsed time? 38*2abb3134SXin Li result='OK' 39*2abb3134SXin Li ;; 40*2abb3134SXin Li 9) 41*2abb3134SXin Li # decode_assoc.R will exit 9 if there are no reports AFTER 42*2abb3134SXin Li # --remove-bad-rows. A task can also be marked SKIPPED before running 43*2abb3134SXin Li # the child process (see backfill.sh). 44*2abb3134SXin Li result='SKIPPED by child process' 45*2abb3134SXin Li ;; 46*2abb3134SXin Li # exit code 142 means SIGALARM. 128 + 14 = 142. See 'kill -l'. 47*2abb3134SXin Li 142) 48*2abb3134SXin Li local seconds=$1 49*2abb3134SXin Li result="TIMEOUT after $seconds seconds" 50*2abb3134SXin Li ;; 51*2abb3134SXin Li *) 52*2abb3134SXin Li result="FAIL with status $exit_code" 53*2abb3134SXin Li ;; 54*2abb3134SXin Li esac 55*2abb3134SXin Li echo "$result" 56*2abb3134SXin Li echo "$result" > $status_file 57*2abb3134SXin Li} 58*2abb3134SXin Li 59*2abb3134SXin Li_work() { 60*2abb3134SXin Li local n=10 # 2 seconds 61*2abb3134SXin Li for i in $(seq $n); do 62*2abb3134SXin Li echo $i - "$@" 63*2abb3134SXin Li sleep 0.2 64*2abb3134SXin Li done 65*2abb3134SXin Li} 66*2abb3134SXin Li 67*2abb3134SXin Li_succeed() { 68*2abb3134SXin Li _work "$@" 69*2abb3134SXin Li exit 0 70*2abb3134SXin Li} 71*2abb3134SXin Li 72*2abb3134SXin Li_fail() { 73*2abb3134SXin Li _work "$@" 74*2abb3134SXin Li exit 1 75*2abb3134SXin Li} 76*2abb3134SXin Li 77*2abb3134SXin Li_skip() { 78*2abb3134SXin Li exit 9 79*2abb3134SXin Li} 80*2abb3134SXin Li 81*2abb3134SXin Li# http://perldoc.perl.org/functions/alarm.html 82*2abb3134SXin Li# 83*2abb3134SXin Li# Delivers alarm. But how to get the process to have a distinct exit code? 84*2abb3134SXin Li 85*2abb3134SXin Lidemo() { 86*2abb3134SXin Li mkdir -p _tmp 87*2abb3134SXin Li 88*2abb3134SXin Li # timeout 89*2abb3134SXin Li alarm-status _tmp/A 1 $0 _succeed foo 90*2abb3134SXin Li echo 91*2abb3134SXin Li 92*2abb3134SXin Li # ok 93*2abb3134SXin Li alarm-status _tmp/B 3 $0 _succeed bar 94*2abb3134SXin Li echo 95*2abb3134SXin Li 96*2abb3134SXin Li # fail 97*2abb3134SXin Li alarm-status _tmp/C 3 $0 _fail baz 98*2abb3134SXin Li echo 99*2abb3134SXin Li 100*2abb3134SXin Li # skip 101*2abb3134SXin Li alarm-status _tmp/D 3 $0 _skip baz 102*2abb3134SXin Li echo 103*2abb3134SXin Li 104*2abb3134SXin Li head _tmp/{A,B,C,D} 105*2abb3134SXin Li} 106*2abb3134SXin Li 107*2abb3134SXin Litest-simple() { 108*2abb3134SXin Li alarm-status _tmp/status.txt 1 sleep 2 109*2abb3134SXin Li} 110*2abb3134SXin Li 111*2abb3134SXin Litest-bad-command() { 112*2abb3134SXin Li alarm-status _tmp/status.txt 1 nonexistent_sleep 2 113*2abb3134SXin Li} 114*2abb3134SXin Li 115*2abb3134SXin Li# BUG 116*2abb3134SXin Litest-perl() { 117*2abb3134SXin Li set +o errexit 118*2abb3134SXin Li perl -e 'alarm shift; exec @ARGV or die "ERROR after exec @ARGV"' 1 _sleep 2 119*2abb3134SXin Li echo $? 120*2abb3134SXin Li} 121*2abb3134SXin Li 122*2abb3134SXin Liif test $(basename $0) = 'alarm-lib.sh'; then 123*2abb3134SXin Li "$@" 124*2abb3134SXin Lifi 125