989ad01358d595f619021742182be67c01dd56fd
max
  Wed Sep 9 07:38:59 2026 -0700
UniProt otto: log an interrupted run instead of leaving a dangling START

Killing a run left "START" in runLog.txt with no line after it, which reads
exactly like a run that is still going. doUpdate.sh now traps INT/TERM/HUP, logs
INTERRUPTED, and removes doUniprot.lock, which doUniprot's own atexit handler
does not get to run on a signal and which would otherwise block the next run.

Note the shell only runs the trap once the foreground doUniprot has exited, so
this fires when the whole process group is killed, which is what pkill does and
what actually happens in practice.

refs #38300

diff --git src/hg/utils/otto/uniprot/doUpdate.sh src/hg/utils/otto/uniprot/doUpdate.sh
index 24e6eb34cb9..be9ac5e6dcf 100755
--- src/hg/utils/otto/uniprot/doUpdate.sh
+++ src/hg/utils/otto/uniprot/doUpdate.sh
@@ -25,33 +25,39 @@
 
 # Do not spend 35 minutes downloading UniProt only to find out that the parser cannot
 # start. Run it with --help, which imports lxml and then exits, and stop here if that
 # fails. Invoked exactly the way doUniprot invokes it, so this tests the same python.
 if ! ./uniprotToTab --help > /dev/null 2>&1; then
     logRun "PREFLIGHT-FAIL uniprotToTab cannot start"
     echo "UniProt update did not start: ./uniprotToTab cannot be run."
     echo
     echo "The lxml python module does not import. Rebuild the environment with:"
     echo "    cd /hive/data/outside/otto/uniprot && ./makeVenv.sh"
     echo
     ./uniprotToTab --help 2>&1 | tail -20
     exit 1
 fi
 
+# A killed run would otherwise leave a START with no matching line, which reads the same
+# as a run that is still going. Say it was interrupted, and drop the lock file, which
+# doUniprot's own atexit handler does not get to run on a signal.
+trap 'logRun "INTERRUPTED killed by a signal"; rm -f /hive/data/outside/uniProt/current/doUniprot.lock; exit 130' INT TERM HUP
+
 logRun "START"
 ./doUniprot run > lastRun.log 2>&1
 exitCode=$?
+trap - INT TERM HUP
 logRun "END exit=$exitCode"
 
 if grep -q "Is a doUniprot process already running" lastRun.log ; then
     # A run from last month, or a hand-started one, is still going, or crashed and left
     # its lock file behind. Say so in one line instead of the failure report below: this
     # is not a broken pipeline, but a stale lock does need someone to look at it.
     logRun "LOCKED another doUniprot run holds the lock file"
     echo "UniProt update skipped: another doUniprot run holds the lock file."
     echo "If nothing is running, remove /hive/data/outside/uniProt/current/doUniprot.lock"
     exit 0
 fi
 
 if [ $exitCode -ne 0 ] ; then
     # lastRun.log is overwritten by the next run, so keep a copy. Without one, a
     # failure that nobody reads leaves no trace on disk at all.