aboutsummaryrefslogtreecommitdiff
path: root/pipeline/alarm-lib.sh
diff options
context:
space:
mode:
Diffstat (limited to 'pipeline/alarm-lib.sh')
-rwxr-xr-xpipeline/alarm-lib.sh124
1 files changed, 124 insertions, 0 deletions
diff --git a/pipeline/alarm-lib.sh b/pipeline/alarm-lib.sh
new file mode 100755
index 0000000..90495ce
--- /dev/null
+++ b/pipeline/alarm-lib.sh
@@ -0,0 +1,124 @@
+#!/bin/bash
+#
+# Alarm tool.
+#
+# Usage:
+# ./alarm.sh <function name>
+
+# You can source this file and use the alarm-status function.
+
+set -o nounset
+set -o pipefail
+set -o errexit
+
+# Run a command with a timeout, and print its status to a directory.
+#
+# Usage:
+# alarm-status job_dir/STATUS 10 \
+# flaky_command ...
+
+alarm-status() {
+ set +o errexit
+ local status_file=$1
+ shift # everything except the status file goes to perl
+
+ # NOTE: It would be nice to setpgrp() before exec? And then can the signal
+ # be delivered to the entire group, like kill -SIGALRM -PID?
+
+ # NOTE: If we did this in Python, the error message would also be clearer.
+ perl -e 'alarm shift; exec @ARGV or die "ERROR: after exec @ARGV"' "$@"
+ local exit_code=$?
+
+ set -o errexit
+
+ local result=''
+ case $exit_code in
+ 0)
+ # Would be nice to show elapsed time?
+ result='OK'
+ ;;
+ 9)
+ # decode_assoc.R will exit 9 if there are no reports AFTER
+ # --remove-bad-rows. A task can also be marked SKIPPED before running
+ # the child process (see backfill.sh).
+ result='SKIPPED by child process'
+ ;;
+ # exit code 142 means SIGALARM. 128 + 14 = 142. See 'kill -l'.
+ 142)
+ local seconds=$1
+ result="TIMEOUT after $seconds seconds"
+ ;;
+ *)
+ result="FAIL with status $exit_code"
+ ;;
+ esac
+ echo "$result"
+ echo "$result" > $status_file
+}
+
+_work() {
+ local n=10 # 2 seconds
+ for i in $(seq $n); do
+ echo $i - "$@"
+ sleep 0.2
+ done
+}
+
+_succeed() {
+ _work "$@"
+ exit 0
+}
+
+_fail() {
+ _work "$@"
+ exit 1
+}
+
+_skip() {
+ exit 9
+}
+
+# http://perldoc.perl.org/functions/alarm.html
+#
+# Delivers alarm. But how to get the process to have a distinct exit code?
+
+demo() {
+ mkdir -p _tmp
+
+ # timeout
+ alarm-status _tmp/A 1 $0 _succeed foo
+ echo
+
+ # ok
+ alarm-status _tmp/B 3 $0 _succeed bar
+ echo
+
+ # fail
+ alarm-status _tmp/C 3 $0 _fail baz
+ echo
+
+ # skip
+ alarm-status _tmp/D 3 $0 _skip baz
+ echo
+
+ head _tmp/{A,B,C,D}
+}
+
+test-simple() {
+ alarm-status _tmp/status.txt 1 sleep 2
+}
+
+test-bad-command() {
+ alarm-status _tmp/status.txt 1 nonexistent_sleep 2
+}
+
+# BUG
+test-perl() {
+ set +o errexit
+ perl -e 'alarm shift; exec @ARGV or die "ERROR after exec @ARGV"' 1 _sleep 2
+ echo $?
+}
+
+if test $(basename $0) = 'alarm-lib.sh'; then
+ "$@"
+fi