Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DEBUG trap is not reset when running a script without a shebang #1458

Open
petrpavlu opened this issue Jan 17, 2020 · 0 comments
Open

DEBUG trap is not reset when running a script without a shebang #1458

petrpavlu opened this issue Jan 17, 2020 · 0 comments

Comments

@petrpavlu
Copy link

Description of problem:

When a DEBUG trap is registered in a parent shell and then a child shell is invoked to run a script without a shebang, the DEBUG trap is not reset in the forked shell.

My understanding is that when a subshell is entered, traps should be set to the default actions (POSIX 2004 reference).

Ksh version:

  • sh (AT&T Research) 2020.0.0
  • Current Git revision: 031d73a.

How reproducible:

Always.

Steps to reproduce:

$ echo "echo test" > test.sh 
$ chmod +x test.sh
$ function log_debug { echo "DEBUG ${.sh.command}"; }
$ trap log_debug DEBUG
$ ./test.sh
DEBUG ./test.sh
./test.sh: line 1: log_debug: not found
test

Note: When invoking a script with a proper shebang, the DEBUG trap is reset:

$ cat <<EOF > test2.sh
> #!/bin/ksh
> echo test
> EOF
$ chmod +x test2.sh
$ function log_debug { echo "DEBUG ${.sh.command}"; }
$ trap log_debug DEBUG
$ ./test2.sh
DEBUG ./test2.sh
test

Actual results:

DEBUG trap remains set in a child shell.

Expected results:

DEBUG trap is not set in a child shell.

Additional info:

My understanding is that the following happens when running the above mentioned example test.sh:

  • Function path_spawn() (src/cmd/ksh93/sh/path.c) is executed to spawn ./test.sh.

  • It ends up running the execve("./test.sh", ...) syscall which returns ENOEXEC because of the missing shebang.

  • Function path_spawn() recognizes this failure and instead forks the running ksh process to execute the script: path_spawn() -> exscript().

  • Function exscript() ends up passing control via a series of long jumps to sh_main() (src/cmd/ksh93/sh/main.c) which calls sh_reinit() (src/cmd/ksh93/sh/init.c).

  • Function sh_reinit() re-initializes the shell to a clean state. It removes the user-defined function log_debug() and clears also some knowledge of trap handlers, in particular it calls sh_sigreset().

  • Function sh_sigreset() contains the following code:

    for(sig=SH_DEBUGTRAP-1;sig>=0;sig--)
    {
            if(trap=sh.st.trap[sig])
            {
                    if(mode)
                            free(trap);
                    sh.st.trap[sig] = 0;
            }
    
    }
    

    The loop starts from SH_DEBUGTRAP-1 and so the DEBUG trap is not reset.

  • The script invokes command echo test which triggers the debug handler and ksh reports that log_debug() is not available.

Naively, my initial impression was that the above loop should start from SH_DEBUGTRAP and not SH_DEBUGTRAP-1 because the trap array is declared in src/cmd/ksh93/include/defs.h as char *trap[SH_DEBUGTRAP+1]. However, a colleague pointed out to me that this might not be a simple off-by-one error because the code was consciously changed from SH_DEBUGTRAP to SH_DEBUGTRAP-1 in ksh93t. Unfortunately, it is not clear to me from its changelog why this was done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant