kjo
kjo

Reputation: 35311

Terminating a shell function non-interactively

Is there a way to terminate a shell function non-interactively without killing the shell that's running it?

I know that the shell can be told how to respond to a signal (e.g. USR1), but I can't figure out how the signal handler would terminate the function.

If necessary you may assume that the function to be terminate has been written in such a way that it is "terminable" (i.e. by declaring some suitable options).

(My immediate interest is in how to do this for zsh, but I'm also interested in knowing how to do it for bash and for /bin/sh.)

EDIT: In response to Rob Watt's suggestion:

% donothing () { echo $$; sleep 1000000 }
% donothing
47139

If at this point I hit Ctrl-C at the same terminal that is running the shell, then the function donothing does indeed terminate, and I get the command prompt back. But if instead, from a different shell session, I run

% kill -s INT 47139

...the donothing function does not terminate.

Upvotes: 1

Views: 689

Answers (1)

clt60
clt60

Reputation: 63902

Maybe I'm not fully understand what you want, but maybe something like this?

trap "stopme=1" 2

function longcycle() {
    last=$1
    for i in 1 2 3 4 5 
    do
        [ ! -z "$stopme" ] && return
        echo $i
        sleep 1
    done
}

stopme=""
echo "Start 1st cycle"
longcycle
echo "1st cycle end"

echo "2nd cycle"
stopme=""
longcycle
echo "2nd cycle end"

The above is for bash. Run it, and try press CTRL-C.

Or for not interactively, Save the above as for example my_command, then try:

$ ./my_command &  #into background
$ kill -2 $! #send CTRL-C to the bg process

EDIT:

Solution for your sleep example in the bash:

$ donothing() { trap '[[ $mypid ]] && trap - 2 && kill $mypid' 0 2; sleep 1000000 & mypid=$!;wait; }
$ donothing

when you send a signal from another terminal will terminate it. Remeber, signal '0' je "normal end of the process". Semantic name: 0=EXIT, 2=INT... etc.

and remeber too, than signals are sending to processes not to the functions. In your example, the process is the current (interactive shell), so must use the wait trick to get something interrupt-able... Not a nice solution - but the only way when want interrupt something what is running in interactive shell (not a forked one) from the another terminal...

Upvotes: 1

Related Questions