* 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 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-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
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).