diff options
author | Peter Stephenson <pws@zsh.org> | 2016-02-17 10:40:55 +0000 |
---|---|---|
committer | Peter Stephenson <pws@zsh.org> | 2016-02-17 10:40:55 +0000 |
commit | ab74c86edb30fa04fda5fe7fa01e404334f7c2b0 (patch) | |
tree | 096002145a76bca90e09c2dc511008f33145acc2 | |
parent | f96a0167289d41d583b01b17482bba0641be2805 (diff) | |
download | zsh-ab74c86edb30fa04fda5fe7fa01e404334f7c2b0.tar.gz zsh-ab74c86edb30fa04fda5fe7fa01e404334f7c2b0.tar.xz zsh-ab74c86edb30fa04fda5fe7fa01e404334f7c2b0.zip |
37999: Sticky behaviour of EXIT traps.
They now have POSIX or non-POSIX behaviour based on the setting of POSIX_TRAPS where the trap was defined, rather than where the trap would (or would not) be executed. Tweaks possible.
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | README | 14 | ||||
-rw-r--r-- | Src/signals.c | 46 | ||||
-rw-r--r-- | Test/C03traps.ztst | 20 |
4 files changed, 77 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog index 92c50cd46..fe1156f70 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2016-02-17 Peter Stephenson <p.stephenson@samsung.com> + + * 37999: README, Src/signals.c, Test/C03traps.ztst: Make + POSIX-style EXIT traps behave according to POSIX_TRAPS at + the point where the trap is set. + 2016-02-16 Daniel Shahaf <d.s@daniel.shahaf.name> * users/21256 + workers/37965: Doc/Zsh/contrib.yo, diff --git a/README b/README index 8b8ab5731..d5343db19 100644 --- a/README +++ b/README @@ -65,6 +65,20 @@ remainder of the value discarded. This could lead to different behaviour if the argument contains non-numeric characters, or if the argument has leading zeroes and the OCTAL_ZEROES option is set. +3) For some time the shell has had a POSIX_TRAPS option which determines +whether the EXIT trap has POSIX behaviour (the trap is only run at shell +exit) or traditional zsh behaviour (the trap is run once and discarded +when the enclosing fuction or shell exits, whichever happens first). +The use of this option has now been made "sticky" on the EXIT trap --- +in other words, the setting of the option at the point where the trap is +set now determines whether the trap has POSIX or traditional zsh +behaviour. This means that changing the option after the trap was set +no longer has any effect. + +Other aspects of EXIT trap handling have not changed --- there is still +only one EXIT trap at any point in a programme, so it is not generally +useful to combine POSIX and non-POSIX behaviour in the same script. + Incompatibilities between 5.0.8 and 5.2 --------------------------------------- diff --git a/Src/signals.c b/Src/signals.c index aa0b5aaa7..32452ae4f 100644 --- a/Src/signals.c +++ b/Src/signals.c @@ -55,6 +55,15 @@ mod_export Eprog siglists[VSIGCOUNT]; /**/ mod_export int nsigtrapped; +/* + * Flag that exit trap has been set in POSIX mode. + * The setter's expectation is therefore that it is run + * on programme exit, not function exit. + */ + +/**/ +static int exit_trap_posix; + /* Variables used by signal queueing */ /**/ @@ -755,7 +764,7 @@ killjb(Job jn, int sig) * at once, so just use a linked list. */ struct savetrap { - int sig, flags, local; + int sig, flags, local, posix; void *list; }; @@ -774,6 +783,7 @@ dosavetrap(int sig, int level) st = (struct savetrap *)zalloc(sizeof(*st)); st->sig = sig; st->local = level; + st->posix = (sig == SIGEXIT) ? exit_trap_posix : 0; if ((st->flags = sigtrapped[sig]) & ZSIG_FUNC) { /* * Get the old function: this assumes we haven't added @@ -873,6 +883,10 @@ settrap(int sig, Eprog l, int flags) * works just the same. */ sigtrapped[sig] |= (locallevel << ZSIG_SHIFT) | flags; + if (sig == SIGEXIT) { + /* Make POSIX behaviour of EXIT trap sticky */ + exit_trap_posix = isset(POSIXTRAPS); + } unqueue_signals(); return 0; } @@ -908,7 +922,7 @@ removetrap(int sig) * already one at the current locallevel we just overwrite it. */ if (!dontsavetrap && - (sig == SIGEXIT ? !isset(POSIXTRAPS) : isset(LOCALTRAPS)) && + (sig == SIGEXIT ? !exit_trap_posix : isset(LOCALTRAPS)) && locallevel && (!trapped || locallevel > (sigtrapped[sig] >> ZSIG_SHIFT))) dosavetrap(sig, locallevel); @@ -935,6 +949,8 @@ removetrap(int sig) #endif sig != SIGCHLD) signal_default(sig); + if (sig == SIGEXIT) + exit_trap_posix = 0; /* * At this point we free the appropriate structs. If we don't @@ -978,7 +994,7 @@ starttrapscope(void) * so give it the next higher one. dosavetrap() is called * automatically where necessary. */ - if (sigtrapped[SIGEXIT] && !isset(POSIXTRAPS)) { + if (sigtrapped[SIGEXIT] && !exit_trap_posix) { locallevel++; unsettrap(SIGEXIT); locallevel--; @@ -1005,7 +1021,7 @@ endtrapscope(void) * Don't do this inside another trap. */ if (!intrap && - !isset(POSIXTRAPS) && (exittr = sigtrapped[SIGEXIT])) { + !exit_trap_posix && (exittr = sigtrapped[SIGEXIT])) { if (exittr & ZSIG_FUNC) { exitfn = removehashnode(shfunctab, "TRAPEXIT"); } else { @@ -1031,7 +1047,9 @@ endtrapscope(void) if (st->flags & ZSIG_FUNC) settrap(sig, NULL, ZSIG_FUNC); else - settrap(sig, (Eprog) st->list, 0); + settrap(sig, (Eprog) st->list, 0); + if (sig == SIGEXIT) + exit_trap_posix = st->posix; dontsavetrap--; /* * counting of nsigtrapped should presumably be handled @@ -1042,16 +1060,26 @@ endtrapscope(void) if ((sigtrapped[sig] = st->flags) & ZSIG_FUNC) shfunctab->addnode(shfunctab, ((Shfunc)st->list)->node.nam, (Shfunc) st->list); - } else if (sigtrapped[sig]) - unsettrap(sig); + } else if (sigtrapped[sig]) { + /* + * Don't restore the old state if someone has set a + * POSIX-style exit trap --- allow this to propagate. + */ + if (sig != SIGEXIT || !exit_trap_posix) + unsettrap(sig); + } zfree(st, sizeof(*st)); } } if (exittr) { - if (!isset(POSIXTRAPS)) - dotrapargs(SIGEXIT, &exittr, exitfn); + /* + * We already made sure this wasn't set as a POSIX exit trap. + * We respect the user's intention when the trap in question + * was set. + */ + dotrapargs(SIGEXIT, &exittr, exitfn); if (exittr & ZSIG_FUNC) shfunctab->freenode((HashNode)exitfn); else diff --git a/Test/C03traps.ztst b/Test/C03traps.ztst index 4b2843a47..d8183a428 100644 --- a/Test/C03traps.ztst +++ b/Test/C03traps.ztst @@ -399,6 +399,26 @@ >} >No, really exited + (cd ..; $ZTST_exe -fc 'unsetopt posixtraps; + echo start program + emulate sh -c '\''testfn() { + echo start function + set -o | grep posixtraps + trap "echo EXIT TRAP TRIGGERED" EXIT + echo end function + }'\'' + testfn + echo program continuing + echo end of program') +0:POSIX_TRAPS effect on EXIT trap is sticky +>start program +>start function +>noposixtraps off +>end function +>program continuing +>end of program +>EXIT TRAP TRIGGERED + (set -e printf "a\nb\n" | while read line do |