From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 16748 invoked by alias); 29 Dec 2013 13:53:53 -0000 Mailing-List: contact zsh-users-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Users List List-Post: List-Help: X-Seq: 18261 Received: (qmail 1802 invoked from network); 29 Dec 2013 13:53:38 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham version=3.3.2 Date: Sun, 29 Dec 2013 07:35:55 -0600 From: Chris Johnson To: zsh-users@zsh.org Subject: Re: The Halting Problem Message-ID: <20131229133554.GA46017@cs2666372x> References: <20131228164937.GA44192@cs2666372x.uwec.edu> <131228124348.ZM27114@torch.brasslantern.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <131228124348.ZM27114@torch.brasslantern.com> User-Agent: Mutt/1.5.21 (2010-09-15) X-OriginalArrivalTime: 29 Dec 2013 13:35:26.0988 (UTC) FILETIME=[D57764C0:01CF049A] Bart Schaefer sent me the following 1.0K: > } This kills the long-running job on timeout, but it also puts the job > } in the background. Control-C won't kill it. > > You're almost there. If ctrl+c won't kill the java process in the above > example, then there's some additional signal handling going on behind > the scenes, and you just need to add a trap before the "wait"... Bart, this is great. Thanks! I've generalized the script so that it takes an arbitrary long-running command through ARGV (like time) and kills it after the specified number of seconds: #!/usr/bin/env zsh if [[ $# -lt 2 ]]; then echo "Usage: $0 nseconds command [arg1 [arg2 ...]]" >&2 exit 1 fi nseconds=$1 shift # The command to run is in ARGV[2..]. cmd is going to be embedded in a # string, so we'll need to do some quoting of # its elements to ensure # correct interpolation. cmd=(${(q-)@}) # Kills the specified process after nseconds have expired. sleepkill() { sleep $1 kill $2 print "Command $cmd timed out." } # Start up both the long-running process and a sleep timer. The parentheses # are needed to background the entire cmd, not just its last subcommand. eval "($cmd) &" longpid=$! sleepkill $nseconds $longpid & sleeppid=$! # By default, Control-C will kill the wait that happens below -- and not # longpid. I want it to kill longpid and the sleep timer. TRAPINT() { kill $longpid kill -HUP -$$ } # If longpid has already finished, wait will flash a message saying it doesn't # know about the process. I don't want to see that message. wait $longpid 2>/dev/null # If longpid finishes before the sleep timer, let's kill the sleep timer. kill $sleeppid 2>/dev/null If you see any improvements that can be made, I welcome input. -- Chris Johnson johnch@uwec.edu http://www.cs.uwec.edu/~johnch