On Tue, 10 Jul 2007, Clint Pachl wrote:

> I wanted to know if others thought pdksh v5.2.14's behavior is incorrect when
> trapping the EXIT and ERR. I wrote four tests to demonstrate. TEST_1 fails in
> my opinion. I believe it should output the following:
> ERR
> EXIT
> 
> 
> # TEST_1
> trap 'echo EXIT' EXIT
> trap 'echo ERR' ERR
> set -e
> cd /XXXXX 2>/dev/null
> echo DONE
> exit 0
> =====OUTPUT=====(BAD)
> EXIT
> 
> 
> # TEST_2
> trap 'echo EXIT' EXIT
> trap 'echo ERR' ERR
> #set -e
> cd /XXXXX 2>/dev/null
> echo DONE
> exit 0
> =====OUTPUT=====(GOOD)
> ERR
> DONE
> EXIT
> 
> 
> # TEST_3
> #trap 'echo EXIT' EXIT
> trap 'echo ERR' ERR
> set -e
> cd /XXXXX 2>/dev/null
> echo DONE
> exit 0
> =====OUTPUT=====(GOOD)
> ERR
> 
> 
> # TEST_4
> trap 'echo EXIT' EXIT
> #trap 'echo ERR' ERR
> set -e
> cd /XXXXX 2>/dev/null
> echo DONE
> exit 0
> =====OUTPUT=====(GOOD)
> EXIT
> 
> 
> I also tried the tests in at&t ksh93. For TEST_[234], the output is the same
> as above. For TEST_1, it "correctly" outputs:
> ERR
> EXIT
> 
> 
> After a quick grep through /usr/src/bin/ksh for EXIT and ERR I made a quick
> change to main.c. I also found the comment interesting.
> 
> --- main.c      Tue Jul 10 18:43:22 2007
> +++ /usr/src/bin/ksh/main.c     Tue May 15 18:56:46 2007
> @@ -582,12 +582,12 @@
> unwind(int i)
> {
>        /* ordering for EXIT vs ERR is a bit odd (this is what at&t ksh does)
> */
> -       if (Flag(FERREXIT) && (i == LERROR || i == LINTR)) {
> -               runtrap(&sigtraps[SIGERR_]);
> -               i = LLEAVE;
> -       } else if (i == LEXIT || (Flag(FERREXIT) && (i == LERROR || i ==
> LINTR) &&
> +       if (i == LEXIT || (Flag(FERREXIT) && (i == LERROR || i == LINTR) &&
>            sigtraps[SIGEXIT_].trap)) {
>                runtrap(&sigtraps[SIGEXIT_]);
> +               i = LLEAVE;
> +       } else if (Flag(FERREXIT) && (i == LERROR || i == LINTR)) {
> +               runtrap(&sigtraps[SIGERR_]);
>                i = LLEAVE;
>        }
>        while (1) {
> 
> 
> After applying the patch above, TEST_1 outputs "ERR" instead of "EXIT." This
> seems closer, just need to comeback and run the EXIT trap. If people think
> this is a bug I will investigate further.
> 
> Also, according to OBSD's ksh(1) man page, TEST_1 hints at a possible bug.
> 
> set command
> ...
> -e | errexit     Exit (after executing the ERR trap) as soon as
>                  an error occurs or a command fails (i.e. exits
>                  with a non-zero status).  This does not apply to
>                  commands whose exit status is explicitly tested
>                  by a shell construct such as if, until, while,
>                  &&, or || statements.
> 
> -pachl
> 
> 

Yes, there are bugs wrt to ERR and EXIT traps. I have this diff in my
tree, which solves the case below (ERR handler is not called) and your
first test case.  Will look into your diff later. Test case originally
by grunk@

        -Otto

Index: exec.c
===================================================================
RCS file: /cvs/src/bin/ksh/exec.c,v
retrieving revision 1.46
diff -u -p -r1.46 exec.c
--- exec.c      10 Apr 2006 14:38:59 -0000      1.46
+++ exec.c      11 Jul 2007 05:55:17 -0000
@@ -363,9 +363,9 @@ execute(struct op *volatile t,
        if ((flags&XEXEC))
                unwind(LEXIT);  /* exit child */
        if (rv != 0 && !(flags & XERROK)) {
+               trapsig(SIGERR_);
                if (Flag(FERREXIT))
                        unwind(LERROR);
-               trapsig(SIGERR_);
        }
        return rv;
 }

#!/bin/sh

set -e

handler() {
        echo "INT"
}

errhandler() {
        echo "ERR"
}

exithandler() {
        echo "EXIT"
}

# Bug: leaving out one of the signals causes no output on ^C
trap handler INT
trap exithandler EXIT
trap errhandler ERR
trap handler HUP

trap

cat <<EOF
Interrupt me with ^C to see what happens.
Waiting 600s now...
EOF
sleep 600
echo "Finished."

Reply via email to