Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Fix for EXIT traps
- X-seq: zsh-workers 2896
- From: Peter Stephenson <pws@xxxxxx>
- To: zsh-workers@xxxxxxxxxxxxxxx (Zsh hackers list)
- Subject: Fix for EXIT traps
- Date: Tue, 11 Feb 1997 14:25:28 +0100
A trap for SIGEXIT is supposed to be sprung in the calling
environment; this is its primary use for functions. To make this
consistent, that means that the trap for SIGEXIT should itself reflect
the caller when the trap is sprung. For example,
% fn() { trap 'trap "Exit trap for calling shell" EXIT' EXIT }
% fn
is the way to set an EXIT trap in the parent shell of a function.
Currently zsh doesn't handle this correctly.
This patch fixes this. In fact, it's only been worth handling
correctly seen Zoltan fixed traps in the form given above; before
that, all traps ran as a separate function and these subtleties were
lost (and debugging was a lot more difficult). Much of the patch is a
minor rewrite to dotrap() which allows the code to be called for
signal functions which are not currently installed.
I have also been careful to make code like:
% trap 'echo The original exit trap' EXIT
% fn() { trap 'trap >storeoldtraps' EXIT; }
% fn
% cat storeoldtraps
trap -- 'echo The original exit trap' EXIT
work too. (Unfortunately, `storeoldtraps=$(trap)' doesn't work,
although it does in ksh. Whether this is the right effect in a
subshell is not clear.)
If anyone can think of a workaround for setting an EXIT trap for a
shell from within a function, I'd be interested to hear it anyway. I
can only think of some rather brutal asynchronous possibilities.
*** Src/exec.c.se Wed Feb 5 15:53:02 1997
--- Src/exec.c Tue Feb 11 13:53:00 1997
***************
*** 2515,2524 ****
{
Param pm;
char **tab, **x, *oargv0 = NULL;
! int xexittr, oldzoptind, oldlastval;
LinkList olist;
char *s, *ou;
! void *xexitfn;
char saveopts[OPT_SIZE];
int obreaks = breaks;
--- 2515,2524 ----
{
Param pm;
char **tab, **x, *oargv0 = NULL;
! int xexittr, newexittr, oldzoptind, oldlastval;
LinkList olist;
char *s, *ou;
! void *xexitfn, *newexitfn;
char saveopts[OPT_SIZE];
int obreaks = breaks;
***************
*** 2610,2620 ****
opts[LOCALOPTIONS] = saveopts[LOCALOPTIONS];
}
! /* Did the shell function define a trap on SIGEXIT? */
! if (sigfuncs[SIGEXIT]) {
! dotrap(SIGEXIT);
! unsettrap(SIGEXIT);
! }
sigtrapped[SIGEXIT] = xexittr;
if (xexittr & ZSIG_FUNC) {
--- 2610,2624 ----
opts[LOCALOPTIONS] = saveopts[LOCALOPTIONS];
}
! /*
! * The trap '...' EXIT runs in the environment of the caller,
! * so remember it here but run it after resetting the
! * traps for the parent.
! */
! newexittr = sigtrapped[SIGEXIT];
! newexitfn = sigfuncs[SIGEXIT];
! if (newexittr & ZSIG_FUNC)
! shfunctab->removenode(shfunctab, "TRAPEXIT");
sigtrapped[SIGEXIT] = xexittr;
if (xexittr & ZSIG_FUNC) {
***************
*** 2622,2627 ****
--- 2626,2637 ----
sigfuncs[SIGEXIT] = ((Shfunc) xexitfn)->funcdef;
} else
sigfuncs[SIGEXIT] = (List) xexitfn;
+
+ if (newexitfn) {
+ dotrapargs(SIGEXIT, &newexittr, newexitfn);
+ freestruct(newexitfn);
+ }
+
if (trapreturn < -1)
trapreturn++;
if (noreturnval)
*** Src/signals.c.se Tue Feb 11 13:27:46 1997
--- Src/signals.c Tue Feb 11 13:49:50 1997
***************
*** 655,665 ****
}
}
! /* Execute a trap function for a given signal */
/**/
void
! dotrap(int sig)
{
LinkList args;
char *name, num[4];
--- 655,667 ----
}
}
! /* Execute a trap function for a given signal, possibly
! * with non-standard sigtrapped & sigfuncs values
! */
/**/
void
! dotrapargs(int sig, int *sigtr, void *sigfn)
{
LinkList args;
char *name, num[4];
***************
*** 674,688 ****
* intact without working too hard. Special cases (e.g. calling *
* a trap for SIGINT after the error flag was set) are handled *
* by the calling code. (PWS 1995/06/08). */
! if ((sigtrapped[sig] & ZSIG_IGNORED) || !sigfuncs[sig] || errflag)
return;
! sigtrapped[sig] |= ZSIG_IGNORED;
lexsave();
execsave();
breaks = 0;
! if (sigtrapped[sig] & ZSIG_FUNC) {
PERMALLOC {
args = newlinklist();
name = (char *) zalloc(5 + strlen(sigs[sig]));
--- 676,690 ----
* intact without working too hard. Special cases (e.g. calling *
* a trap for SIGINT after the error flag was set) are handled *
* by the calling code. (PWS 1995/06/08). */
! if ((*sigtr & ZSIG_IGNORED) || !sigfn || errflag)
return;
! *sigtr |= ZSIG_IGNORED;
lexsave();
execsave();
breaks = 0;
! if (*sigtr & ZSIG_FUNC) {
PERMALLOC {
args = newlinklist();
name = (char *) zalloc(5 + strlen(sigs[sig]));
***************
*** 692,702 ****
addlinknode(args, num);
} LASTALLOC;
trapreturn = -1;
! doshfunc(sigfuncs[sig], args, 0, 1);
freelinklist(args, (FreeFunc) NULL);
zsfree(name);
} else HEAPALLOC {
! execlist(dupstruct(sigfuncs[sig]), 1, 0);
} LASTALLOC;
if (trapreturn > 0)
trapret = trapreturn;
--- 694,704 ----
addlinknode(args, num);
} LASTALLOC;
trapreturn = -1;
! doshfunc(sigfn, args, 0, 1);
freelinklist(args, (FreeFunc) NULL);
zsfree(name);
} else HEAPALLOC {
! execlist(dupstruct(sigfn), 1, 0);
} LASTALLOC;
if (trapreturn > 0)
trapret = trapreturn;
***************
*** 714,719 ****
breaks = loops;
}
! if (sigtrapped[sig] != ZSIG_IGNORED)
! sigtrapped[sig] &= ~ZSIG_IGNORED;
}
--- 716,730 ----
breaks = loops;
}
! if (*sigtr != ZSIG_IGNORED)
! *sigtr &= ~ZSIG_IGNORED;
! }
!
! /* Standard call to execute a trap for a given signal */
!
! /**/
! void
! dotrap(int sig)
! {
! dotrapargs(sig, sigtrapped+sig, sigfuncs[sig]);
}
--
Peter Stephenson <pws@xxxxxx> Tel: +49 33762 77366
WWW: http://www.ifh.de/~pws/ Fax: +49 33762 77413
Deutsches Elektronen-Synchrotron --- Institut fuer Hochenergiephysik Zeuthen
DESY-IfH, 15735 Zeuthen, Germany.
Messages sorted by:
Reverse Date,
Date,
Thread,
Author