zsh-users
 help / color / mirror / code / Atom feed
* localtraps
@ 2005-04-25  6:35 Vincent Stemen
  2005-04-25 16:32 ` localtraps Bart Schaefer
  0 siblings, 1 reply; 10+ messages in thread
From: Vincent Stemen @ 2005-04-25  6:35 UTC (permalink / raw)
  To: zsh-users

Hi.

I don't seem to be able to get the localtraps option to work.

Here is my test script

<test script>

#!/bin/zsh
# sigtest

signal()
{
    setopt LOCAL_TRAPS
    trap "echo 'executing local signal() trap'" INT
    echo "--- got signal ---"
    sleep 2
}

trap signal INT


for n in 1 2 3 4 5 6
do
    echo -n "."
    sleep 1
done

echo

</test script>


<My expected result>

I expected to see "--- got signal ---" if I hit ^C, then, if I hit ^C
again within 2 seconds, before it exits signal(), I expected to see
"executing local signal() trap".  If I wait at least 2 seconds until I
see another '.' printed, then hit ^C again, I expected to see
"--- got signal ---" again.

</expected result>

On  zsh 4.2.0 (i386-unknown-freebsd5.2.1)
the trap inside signal() seems to have no effect.  Here is what I got

# ./sigtest
.^C--- got signal ---
^C--- got signal ---
^C--- got signal ---
..^C--- got signal ---
..

If I do not set localtraps, then the trap inside signal() works as
expected.

# ./sigtest

^C--- got signal ---
^Cexecuting local signal() trap
.^Cexecuting local signal() trap
.^Cexecuting local signal() trap
..^Cexecuting local signal() trap
.


On zsh 4.2.1 (i386--netbsdelf)
I got a different result with localtraps set.

# ./sigtest
.^C--- got signal ---
^C^Cexecuting local signal() trap
..^Cexecuting local signal() trap
...


As you can see, on 4.2.1 the trap inside signal() works, but the
"setopt LOCAL_TRAPS" has no effect.  It never resets the signal back
when it exits the signal() function.

If I was doing something wrong, I expected to get the same result on
both systems.  Am I overlooking something?

Regards,
Vincent

-- 
Vincent Stemen
Avoid the VeriSign/Network Solutions domain registration trap!
Read how Network Solutions (NSI) was involved in stealing our domain name.
http://www.InetAddresses.net


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: localtraps
  2005-04-25  6:35 localtraps Vincent Stemen
@ 2005-04-25 16:32 ` Bart Schaefer
  2005-04-26  0:50   ` localtraps Vincent Stemen
  2005-04-26  3:03   ` localtraps Vincent Stemen
  0 siblings, 2 replies; 10+ messages in thread
From: Bart Schaefer @ 2005-04-25 16:32 UTC (permalink / raw)
  To: zsh-users

On Apr 25,  1:35am, Vincent Stemen wrote:
} Subject: localtraps
} 
} I don't seem to be able to get the localtraps option to work.

Try it where the outer function is NOT a trap for the same signal
that you're trapping inside the function.

I suspect that changing the trap of the same signal that is trapped
is confusing the trap code, because low-level signal handling already
requires that the signal handler restore itself before exiting, so in 
effect you're restoring multiple different traps, and the order in
which function exit and trap unwinding are processed is mixed up.


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: localtraps
  2005-04-25 16:32 ` localtraps Bart Schaefer
@ 2005-04-26  0:50   ` Vincent Stemen
  2005-04-26  3:03   ` localtraps Vincent Stemen
  1 sibling, 0 replies; 10+ messages in thread
From: Vincent Stemen @ 2005-04-26  0:50 UTC (permalink / raw)
  To: zsh-users

On Mon, Apr 25, 2005 at 04:32:02PM +0000, Bart Schaefer wrote:
> On Apr 25,  1:35am, Vincent Stemen wrote:
> } Subject: localtraps
> } 
> } I don't seem to be able to get the localtraps option to work.
> 
> Try it where the outer function is NOT a trap for the same signal
> that you're trapping inside the function.
> 
> I suspect that changing the trap of the same signal that is trapped
> is confusing the trap code, because low-level signal handling already
> requires that the signal handler restore itself before exiting, so in 
> effect you're restoring multiple different traps, and the order in
> which function exit and trap unwinding are processed is mixed up.

Thanks for the response.

Yes, You are correct.  I tested trapping a different signal in the
signal trap function and the localtraps option did indeed work.

I got the same result on
zsh 4.2.0 (i386-unknown-freebsd5.2.1)
and
zsh 4.0.7 (i386-redhat-linux-gnu)

(Except I had to re-write my test function to not run any additional
utilities such as sleep in order to properly test it on Linux because
of Linux's dumb signal handling.  It does not pass signals on to the
parent process like BSD does.)

On both, if I try to change the trap for the same signal in the trap
handler function with localtraps on, it ignores the new trap.

However, As I mentioned earlier, I get a different behavior on
zsh 4.2.1 (i386--netbsdelf)

It resets the signal trap, rather than ignoring it, but ignores the
localtraps option so that the new trap is still in effect after
exiting the function.

It seems to me that either behavior should be considered a bug in
zsh.  

This renders the localtraps option not useful to me much of the time
because I often need to temporarily disable or modify the function of
the same signal while I am in the signal handler processing it.

Is this an architectural problem with zsh that would be difficult to
fix?

To make it easier for anybody that wants to test it, here is my
re-written and improved test script that generates it's own signals.


#---------------------------------------------
#!/bin/zsh

sigterm1()
{
    setopt LOCAL_TRAPS

    trap sigterm2 TERM
    echo "sigterm1(): sending SIGTERM"
    kill -s TERM $$
}

sigterm2()
{
    echo "sigterm2()"
}


trap sigterm1 TERM

echo
echo "main: sending SIGTERM"
kill -s TERM $$
echo "main: sending SIGTERM"
kill -s TERM $$

echo
#---------------------------------------------


On the versions I mentioned above on Linux and FreeBSD this will
go into an endless loop printing
"sigterm1(): sending SIGTERM"
because the trap statement  in sigterm1() is ignored, unless you
comment out "setopt LOCAL_TRAPS".


-- 
Vincent Stemen
Avoid the VeriSign/Network Solutions domain registration trap!
Read how Network Solutions (NSI) was involved in stealing our domain name.
http://www.InetAddresses.net


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: localtraps
  2005-04-25 16:32 ` localtraps Bart Schaefer
  2005-04-26  0:50   ` localtraps Vincent Stemen
@ 2005-04-26  3:03   ` Vincent Stemen
  2005-04-26 18:34     ` localtraps Peter Stephenson
  1 sibling, 1 reply; 10+ messages in thread
From: Vincent Stemen @ 2005-04-26  3:03 UTC (permalink / raw)
  To: zsh-users

On Mon, Apr 25, 2005 at 04:32:02PM +0000, Bart Schaefer wrote:
> On Apr 25,  1:35am, Vincent Stemen wrote:
> } Subject: localtraps
> } 
> } I don't seem to be able to get the localtraps option to work.
> 
> Try it where the outer function is NOT a trap for the same signal
> that you're trapping inside the function.
> 
> I suspect that changing the trap of the same signal that is trapped
> is confusing the trap code, because low-level signal handling already
> requires that the signal handler restore itself before exiting, so in 
> effect you're restoring multiple different traps, and the order in
> which function exit and trap unwinding are processed is mixed up.

I have some new information.

I had hoped that I could get around the problem for now by explicitly
resetting the signal trap without using localtraps but, as you
indicated, it will not let me do anything with the same signal while
it is in the signal handler function.  This is a real problem that I
don't know how to get around.  Here is a new snippet of test code that
does basically what I am trying to do perfectly under the BSD shell.

#--------------------------------
#!/bin/sh

abort()
{
  echo 
  echo '** Aborting program **'
  echo 

  exit 1
}

signal()
{
  local signal=$1

  if [ -n "$script" ]
  then
      trap abort INT  
      echo -e "\n$0: $script Interrupted.  Hit ^C again to abort everything."
      sleep 2
      echo -n "Continuing "
      trap 'signal INT' INT  # Reset the signal trap for ^C
      return
  else
      abort
  fi
}


script=foo
trap 'signal' INT

echo -n "Doing something important "
for n in 1 2 3 4 5 6 7 8 9
do
    echo -n "."
    sleep 1
done

echo
echo "Exiting normally"
echo
#--------------------------------

Here is the output using the BSD /bin/sh:

# sigtest
Doing something important ..^C
sigtest: foo Interrupted.  Hit ^C again to abort everything.
Continuing ..^C
sigtest: foo Interrupted.  Hit ^C again to abort everything.
^C
** Aborting program **


After the first time I hit ^C, I waited more than 2 seconds.
The second time I hit ^C twice and it called abort() as I wanted.


Trying this under Z shell, I get

# sigtest
Doing something important ..^C
sigtest6: foo Interrupted.  Hit ^C again to abort everything.
^CContinuing
sigtest6: foo Interrupted.  Hit ^C again to abort everything.
^CContinuing
sigtest6: foo Interrupted.  Hit ^C again to abort everything.
Continuing .......
Exiting normally


Since it ignores the trap statement in signal() I have no way of
aborting.

I am using Z shell in all the scripts I am working on because it is
generally so vastly better that bourne shell, but this is a real
handycap.

Any ideas?


-- 
Vincent Stemen
Avoid the VeriSign/Network Solutions domain registration trap!
Read how Network Solutions (NSI) was involved in stealing our domain name.
http://www.InetAddresses.net


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: localtraps
  2005-04-26  3:03   ` localtraps Vincent Stemen
@ 2005-04-26 18:34     ` Peter Stephenson
  2005-04-26 22:12       ` localtraps Vincent Stemen
  2005-04-27  5:36       ` localtraps Bart Schaefer
  0 siblings, 2 replies; 10+ messages in thread
From: Peter Stephenson @ 2005-04-26 18:34 UTC (permalink / raw)
  To: zsh-users

Vincent Stemen wrote:
> I had hoped that I could get around the problem for now by explicitly
> resetting the signal trap without using localtraps but, as you
> indicated, it will not let me do anything with the same signal while
> it is in the signal handler function.  This is a real problem that I
> don't know how to get around.

The problem may be related to the fact that the shell executes traps
from within the signal handler.  Other shells presumably wait for the
handler to exit and execute the trap at the next obvious point (e.g. a
command executed).

However, I've tried this in some recent versions of zsh (4.2.0 and
4.3.0-dev-1, which is a moving target) and it seems to do what I think
you want... abort the programme when you hit ^C twice quickly, otherwise
continue.  So I'm not sure what you're doing wrong.

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070


**********************************************************************
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom they
are addressed. If you have received this email in error please notify
the system manager.

**********************************************************************


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: localtraps
  2005-04-26 18:34     ` localtraps Peter Stephenson
@ 2005-04-26 22:12       ` Vincent Stemen
  2005-04-27  5:59         ` localtraps Bart Schaefer
  2005-04-27  5:36       ` localtraps Bart Schaefer
  1 sibling, 1 reply; 10+ messages in thread
From: Vincent Stemen @ 2005-04-26 22:12 UTC (permalink / raw)
  To: zsh-users

On Tue, Apr 26, 2005 at 07:34:16PM +0100, Peter Stephenson wrote:
> Vincent Stemen wrote:
> > I had hoped that I could get around the problem for now by explicitly
> > resetting the signal trap without using localtraps but, as you
> > indicated, it will not let me do anything with the same signal while
> > it is in the signal handler function.  This is a real problem that I
> > don't know how to get around.
> 
> The problem may be related to the fact that the shell executes traps
> from within the signal handler.  Other shells presumably wait for the
> handler to exit and execute the trap at the next obvious point (e.g. a
> command executed).

I am not sure if this is exactly what you are saying, but zsh on
NetBSD queues the next signal and will not re-call the signal handler
until it exits the handler from the first one.  However, I can trap a
different signal from within the signal handler and if it catches that
new signal, it immediatly re-calls the handler.  It just won't do it
on the same signal.

One thing I tried was to set a flag indicating that the signal had
already hit once so that when it re-calls the sig handler it would
know it was the second time.  That did not work though for the same
reason.  I cannot reset the flag before exiting the function because
it always completes the function before processing the next signal and
re-calling it.  So on the next signal, the flag is always back unset.


> However, I've tried this in some recent versions of zsh (4.2.0 and
> 4.3.0-dev-1, which is a moving target) and it seems to do what I think
> you want... abort the programme when you hit ^C twice quickly, otherwise
> continue.  So I'm not sure what you're doing wrong.

My need generally is not just to require two ^C's to exit.  I often
need to print a message, have a delay, and/or do other work on the
first signal and abort on the second one, or disable the signal all
together while in the handler to perform some function so that another
hit will not re-call the function, and then re-enable the signal just
before exiting the handler.  I also have written scripts before where
I required more than two ^C's to abort in critical sections of code.

Either way, I really need to be able to use the trap command on the
same signal in the handler like I can in the BSD shell.  It would also
be very convenient to be able to use localtraps so that I don't have
to explicitly reset the signal before returning.


-- 
Vincent Stemen
Avoid the VeriSign/Network Solutions domain registration trap!
Read how Network Solutions (NSI) was involved in stealing our domain name.
http://www.InetAddresses.net


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: localtraps
  2005-04-26 18:34     ` localtraps Peter Stephenson
  2005-04-26 22:12       ` localtraps Vincent Stemen
@ 2005-04-27  5:36       ` Bart Schaefer
  1 sibling, 0 replies; 10+ messages in thread
From: Bart Schaefer @ 2005-04-27  5:36 UTC (permalink / raw)
  To: zsh-users

On Apr 26,  7:34pm, Peter Stephenson wrote:
} Subject: Re: localtraps
}
} The problem may be related to the fact that [zsh] executes traps
} from within the signal handler.  Other shells presumably wait for the
} handler to exit and execute the trap at the next obvious point

Normally it's the case that executing the trap from within the signal
handler means that you can't handle the same signal again before the
trap function has exited.  However, I think the only way to get the
behavior I'm seeing is that the "trap" command unblocks the signal
again, allowing it to be re-delivered before the handler finishes (at
least, on linux it looks that way).

Also, it's not universally true that zsh executes traps from inside
the handler; there *is* a queue of unfinished handlers maintained, for
circumstances where it's dangerous to run shell code, e.g., while some
other shell code is executing and possibly calling malloc().  It's only
when the shell is idle that zsh runs the trap in the handler.

} However, I've tried this in some recent versions of zsh (4.2.0 and
} 4.3.0-dev-1, which is a moving target) and it seems to do what I think
} you want... abort the programme when you hit ^C twice quickly, otherwise
} continue.  So I'm not sure what you're doing wrong.

There's definitely something odd about the behavior of zsh here.  For
example, given:

    setopt localtraps
    TRAPINT() { echo OUTER; trap "echo INNER" INT; sleep 2 }

On the first ^C at the PS1 prompt, OUTER is printed, and no new prompt
is drawn.  If I press ^C again within 2 seconds, then a blank line (no
idea why) and INNER is printed, but still no new prompt.  Note that no
shell loop is involved, this with the shell merely waiting for input.

Every subsequent ^C, no matter how long I wait, prints INNER, up until
a newline is pressed, at which point a new prompt is drawn.  Once the
prompt is redrawn, subsequent interrupts do nothing at all (neither
OUTER nor INNER is printed).  However, "trap" with no argument still
shows the original TRAPINT function.

So localtraps eventually worked in the sense that the inner trap was
removed, but the outer trap was never reset in the signal handler.


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: localtraps
  2005-04-26 22:12       ` localtraps Vincent Stemen
@ 2005-04-27  5:59         ` Bart Schaefer
  2005-04-28  1:00           ` localtraps Vincent Stemen
  0 siblings, 1 reply; 10+ messages in thread
From: Bart Schaefer @ 2005-04-27  5:59 UTC (permalink / raw)
  To: zsh-users

On Apr 26,  5:12pm, Vincent Stemen wrote:
}
} One thing I tried was to set a flag indicating that the signal had
} already hit once so that when it re-calls the sig handler it would
} know it was the second time.  That did not work though for the same
} reason.  I cannot reset the flag before exiting the function because
} it always completes the function before processing the next signal and
} re-calling it.  So on the next signal, the flag is always back unset.

This should work with a sufficiently recent version of zsh to have the
"always" construct:

    inner () {
	if ((trips++))
	then
	  {
	    print "Do the multiple-trip thing ..."
	  } always {
	    ((--trips))
	  }
	fi
    }

    outer () {
      {
	setopt localoptions nolocaltraps
	integer -g trips=1
	trap inner INT
	print "Doing something useful now ..."
	sleep 2
      } always {
	unset trips
	trap outer INT
      }
    }
    trap outer INT

With that, even if I press ^C and hold it down, it alternates between
"Doing something useful now ..." and "Do the multiple-trip thing ..."
and ends up with "trips" unset.  Of course, this is on Linux; if you
are right about the NetBSD signal behavior, you'll need something more
subtle.


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: localtraps
  2005-04-27  5:59         ` localtraps Bart Schaefer
@ 2005-04-28  1:00           ` Vincent Stemen
  2005-04-28  8:20             ` localtraps Bart Schaefer
  0 siblings, 1 reply; 10+ messages in thread
From: Vincent Stemen @ 2005-04-28  1:00 UTC (permalink / raw)
  To: zsh-users

On Wed, Apr 27, 2005 at 05:59:07AM +0000, Bart Schaefer wrote:
> On Apr 26,  5:12pm, Vincent Stemen wrote:
> }
> } One thing I tried was to set a flag indicating that the signal had
> } already hit once so that when it re-calls the sig handler it would
> } know it was the second time.  That did not work though for the same
> } reason.  I cannot reset the flag before exiting the function because
> } it always completes the function before processing the next signal and
> } re-calling it.  So on the next signal, the flag is always back unset.
> 
> This should work with a sufficiently recent version of zsh to have the
> "always" construct:
> 
>     inner () {
> 	if ((trips++))
> 	then
> 	  {
> 	    print "Do the multiple-trip thing ..."
> 	  } always {
> 	    ((--trips))
> 	  }
> 	fi
>     }
> 
>     outer () {
>       {
> 	setopt localoptions nolocaltraps
> 	integer -g trips=1
> 	trap inner INT
> 	print "Doing something useful now ..."
> 	sleep 2
>       } always {
> 	unset trips
> 	trap outer INT
>       }
>     }
>     trap outer INT
> 
> With that, even if I press ^C and hold it down, it alternates between
> "Doing something useful now ..." and "Do the multiple-trip thing ..."
> and ends up with "trips" unset.  Of course, this is on Linux; if you
> are right about the NetBSD signal behavior, you'll need something more
> subtle.

I added a sleep at the end to give me time to hit ^C and tested on
NetBSD.  Here is the result.

# sigtest
^CDoing something useful now ...
^C^C^C^C^CDoing something useful now ...
^C^C^CDoing something useful now ...

Which is pretty much what I expected since I cannot reset the trap
in the sig handler.

-- 
Vincent Stemen
Avoid the VeriSign/Network Solutions domain registration trap!
Read how Network Solutions (NSI) was involved in stealing our domain name.
http://www.InetAddresses.net


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: localtraps
  2005-04-28  1:00           ` localtraps Vincent Stemen
@ 2005-04-28  8:20             ` Bart Schaefer
  0 siblings, 0 replies; 10+ messages in thread
From: Bart Schaefer @ 2005-04-28  8:20 UTC (permalink / raw)
  To: zsh-users

On Apr 27,  8:00pm, Vincent Stemen wrote:
} Subject: Re: localtraps
}
} Which is pretty much what I expected since I cannot reset the trap
} in the sig handler.

Did you check whether this has changed following PWS's patch for
localtraps?  (On zsh-workers and now checked in to CVS.)


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2005-04-28  8:20 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-04-25  6:35 localtraps Vincent Stemen
2005-04-25 16:32 ` localtraps Bart Schaefer
2005-04-26  0:50   ` localtraps Vincent Stemen
2005-04-26  3:03   ` localtraps Vincent Stemen
2005-04-26 18:34     ` localtraps Peter Stephenson
2005-04-26 22:12       ` localtraps Vincent Stemen
2005-04-27  5:59         ` localtraps Bart Schaefer
2005-04-28  1:00           ` localtraps Vincent Stemen
2005-04-28  8:20             ` localtraps Bart Schaefer
2005-04-27  5:36       ` localtraps Bart Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).