0

Environment: GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin20)

I'm attempting to trap the exit from another function but then continue executing the program. In an object oriented language you could catch an exception and then continue execution without re-throwin; that is essentially what I'm trying to do. I'm expecting the function foo() to exit, but in this case I want to catch it and continue execution of the program.

#!/bin/bash

function doNotExitProgram()
{
   echo "Ignoring EXIT"
    # Magic happens here
}

trap doNotExitProgram EXIT

function foo()
{
    echo "Inside foo()"
    exit 170
}

foo
echo "Continue execution here"

Expected:

Inside foo()
Ignoring EXIT
Continue execution here

Actual:

Inside foo()
Ignoring EXIT

Steps tried so far:

  1. Tried using shopt -s extdebug but that doesn't seem to work with EXIT.

  2. Tried trap - EXIT inside doNotExitProgram()

  3. Tried trap - EXIT return return 0 inside doNotExitProgram()

  4. Tried trap - EXIT return return 1 inside doNotExitProgram()

  5. Tried return 0 inside doNotExitProgram()

  6. Tried return 1 inside doNotExitProgram()

  7. Tried trap "" EXIT inside doNotExitProgram()

This scenario is not described on Traps on tldp.org or on the trap man page.

EDIT: If possible do not change foo()

2 Answers 2

1

With x option (bash -x file):

+ trap doNotExitProgram EXIT
+ foo
+ echo 'Inside foo()'
Inside foo()
+ exit 170
+ doNotExitProgram
+ echo 'Ignoring EXIT'
Ignoring EXIT

trap doNotExitProgram EXIT happens calling doNotExitProgram when called exit. When call foo, executed doNotExitProgram. exit finish script execution so not executed echo "Continue execution here".

To resolve:

#!/bin/bash

(
  function doNotExitProgram()
  {
    echo "Ignoring EXIT"
      # Magic happens here
  }

  trap doNotExitProgram EXIT

  function foo()
  {
      echo "Inside foo()"
      exit 170
  }

  foo
)
echo "Continue execution here"

Result:

Inside foo()
Ignoring EXIT
Continue execution here

With x option:

+ trap doNotExitProgram EXIT
+ foo
+ echo 'Inside foo()'
Inside foo()
+ exit 170
++ doNotExitProgram
++ echo 'Ignoring EXIT'
Ignoring EXIT
+ echo 'Continue execution here'
Continue execution here

You can set a trap in a subshell. The expected value will be output.

4
  • I'm going to hold off accepting incase there's another solution that doesn't involve a subshell. Feb 16 at 6:41
  • 1
    @YzmirRamirez Since exit terminates the current shell/subshell, the only other way to do this would be to launch a child shell with bash -c '...' in place of the subshell in this answer. You'd be waiting a long time for something better.
    – they
    Feb 16 at 7:05
  • I would prefer not changing the existing code, that's why I wanted a trap only solution. Feb 16 at 15:05
  • I accepted your answer @sakkke, thank you! Feb 18 at 4:28
1

Or using helper function:

#!/bin/bash

function doNotExitProgram()
{
   echo "Ignoring EXIT"
    # Magic happens here
}

function catchExitCode()
{
    case $1 in
        170 )
            doNotExitProgram
            ;;
    esac
}

trap 'catchExitCode $?' DEBUG

function foo()
{
    echo "Inside foo()"
    return 170
}

foo
echo "Continue execution here"

You can add a branching function named catchExitCode. The drawback is that it can be hijacked if other executables return 170. By unique exit code, it can branch logic.

3
  • It seems as if you've solved the issue of not exiting from exit by removing exit. I don't think this was what the user asked for. Also, could you explain the magic constants 130 (only mentioned in text) and 170?
    – they
    Feb 16 at 10:06
  • Sorry, I missed 130 correctly 170. And updated answer. I thought cleaner code than using subshell to use case statement. But this is a matter of taste.
    – sakkke
    Feb 16 at 12:40
  • Ideally I did not want to have to modify the existing code. I'll update that more clearer. +1 for your effort @sakkke Feb 16 at 15:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.