ash: better handling of EXIT trap in `trap` hack
authorDenys Vlasenko <vda.linux@googlemail.com>
Thu, 24 Sep 2009 22:06:51 +0000 (00:06 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Thu, 24 Sep 2009 22:06:51 +0000 (00:06 +0200)
function                                             old     new   delta
forkchild                                              -     602    +602
trapcmd                                              255     347     +92
ash_main                                            1362    1375     +13
evalvar                                             1371    1373      +2
popstring                                            140     134      -6
forkshell                                            835     248    -587
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 3/2 up/down: 709/-593)          Total: 116 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
shell/ash.c
shell/ash_test/ash-signals/savetrap.right
shell/ash_test/ash-signals/savetrap.tests
shell/hush_test/hush-trap/savetrap.right
shell/hush_test/hush-trap/savetrap.tests

index 47f968b5474141dfcef3f5b4c2c2b171177653cd..b30dc77286a42ae787240c602b578c8564cc12ce 100644 (file)
@@ -193,6 +193,7 @@ struct globals_misc {
        /* indicates specified signal received */
        uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
        char *trap[NSIG];
+       char **trap_ptr;        /* used only by "trap hack" */
 
        /* Rarely referenced stuff */
 #if ENABLE_ASH_RANDOM_SUPPORT
@@ -222,6 +223,7 @@ extern struct globals_misc *const ash_ptr_to_globals_misc;
 #define sigmode     (G_misc.sigmode    )
 #define gotsig      (G_misc.gotsig     )
 #define trap        (G_misc.trap       )
+#define trap_ptr    (G_misc.trap_ptr   )
 #define random_galois_LFSR (G_misc.random_galois_LFSR)
 #define random_LCG         (G_misc.random_LCG        )
 #define backgndpid  (G_misc.backgndpid )
@@ -231,6 +233,7 @@ extern struct globals_misc *const ash_ptr_to_globals_misc;
        barrier(); \
        curdir = nullstr; \
        physdir = nullstr; \
+       trap_ptr = trap; \
 } while (0)
 
 
@@ -4539,7 +4542,7 @@ static void closescript(void);
 #if !JOBS
 # define forkchild(jp, n, mode) forkchild(jp, mode)
 #endif
-static void
+static NOINLINE void
 forkchild(struct job *jp, union node *n, int mode)
 {
        int oldlvl;
@@ -4596,8 +4599,10 @@ forkchild(struct job *jp, union node *n, int mode)
                 *
                 * Our solution: ONLY bare $(trap) or `trap` is special.
                 */
-               free(trap[0]); /* Prevent EXIT trap from firing in `trap` */
-               trap[0] = NULL;
+               /* This is needed to prevent EXIT trap firing and such
+                * (trap_ptr will be freed in trapcmd()) */
+               trap_ptr = memcpy(xmalloc(sizeof(trap)), trap, sizeof(trap));
+               memset(trap, 0, sizeof(trap));
        } else {
                clear_traps();
        }
@@ -12260,15 +12265,23 @@ trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
        ap = argptr;
        if (!*ap) {
                for (signo = 0; signo < NSIG; signo++) {
-                       if (trap[signo] != NULL) {
+                       char *tr = trap_ptr[signo];
+                       if (tr) {
                                out1fmt("trap -- %s %s%s\n",
-                                               single_quote(trap[signo]),
+                                               single_quote(tr),
                                                (signo == 0 ? "" : "SIG"),
                                                get_signame(signo));
+                               if (trap_ptr != trap)
+                                       free(tr);
                        }
                }
+               if (trap_ptr != trap) {
+                       free(trap_ptr);
+                       trap_ptr = trap;
+               }
                return 0;
        }
+
        action = NULL;
        if (ap[1])
                action = *ap++;
index 2d33427aa3b0e0eeb92f09343149bb0ba59d1aeb..9cfd7a56c25af840eebc8f5cd66327ca6083a36d 100644 (file)
@@ -1,3 +1,8 @@
+trap -- 'echo Exiting' EXIT
 trap -- 'echo WINCH!' SIGWINCH
+trap -- 'echo Exiting' EXIT
+trap -- 'echo WINCH!' SIGWINCH
+trap -- 'echo Exiting' EXIT
 trap -- 'echo WINCH!' SIGWINCH
 Done
+Exiting
index 6492e86a2ac96213c8d6c1ec700f9246f8a95466..c2b312fb87c206ad435f5fdc15fdbb390707a83d 100755 (executable)
@@ -1,6 +1,9 @@
+trap 'echo Exiting' EXIT
 trap 'echo WINCH!' SIGWINCH
 v=` trap   `
-echo $v
+echo "$v"
+v=$(   trap )
+echo "$v"
 v=`trap`
-echo $v
+echo "$v"
 echo Done
index 2d33427aa3b0e0eeb92f09343149bb0ba59d1aeb..9cfd7a56c25af840eebc8f5cd66327ca6083a36d 100644 (file)
@@ -1,3 +1,8 @@
+trap -- 'echo Exiting' EXIT
 trap -- 'echo WINCH!' SIGWINCH
+trap -- 'echo Exiting' EXIT
+trap -- 'echo WINCH!' SIGWINCH
+trap -- 'echo Exiting' EXIT
 trap -- 'echo WINCH!' SIGWINCH
 Done
+Exiting
index 6492e86a2ac96213c8d6c1ec700f9246f8a95466..c2b312fb87c206ad435f5fdc15fdbb390707a83d 100755 (executable)
@@ -1,6 +1,9 @@
+trap 'echo Exiting' EXIT
 trap 'echo WINCH!' SIGWINCH
 v=` trap   `
-echo $v
+echo "$v"
+v=$(   trap )
+echo "$v"
 v=`trap`
-echo $v
+echo "$v"
 echo Done