4

This is my code:

function my::return() {
    exit_code="$1" 
    echo "exit status of last command: ${exit_code}"
}

function testing(){
    trap 'my::return $?' RETURN
    return 2
}

If I run testing I expect the exit_code to be 2 as tyhis is the code in the return thaat the trap catches.

Stefan Thorpe
  • 540
  • 1
  • 4
  • 11
  • 1
    The `$?` has the exit code of last command executed. The last command was `trap`, so `$?` is 0. Ex see `testing() { trap 'my::return $?' RETURN; false; return 2; }` will set `$?` to the exit code of `false`. However this doesn't take us closer to solution. You can parse `$BASH_COMMAND`, but there should be a way to get this value. – KamilCuk May 09 '19 at 09:19
  • useful workaround: use `(exit 2); return 2` instead of calling only return: https://stackoverflow.com/a/32096622/1329892 – SpinUp __ A Davis Aug 13 '22 at 04:43
  • Duplicates https://stackoverflow.com/questions/32086595/ – JamesThomasMoon Aug 13 '22 at 05:45
  • If you are not using set -e, then the RETURN trap is called twice for a return statement, the first time, without $? set yet, and the second time with $? set according to the return statement. – Johan Boulé Mar 11 '23 at 00:09

3 Answers3

1

This is the best I could come up with

function my-func(){
  trap 'my::return $rc' RETURN
  local rc=2
  return $rc
}
Stefan Thorpe
  • 540
  • 1
  • 4
  • 11
1

This:

#!/usr/bin/env bash

handler(){
        echo "From lineno: $1 exiting with code $2 (last command was: $3)"
        exit "$2"
}

foo(){
        echo "Hey I'm inside foo and will return 123"
        return 123
}

trap 'handler "$LINENO" "$?" "$BASH_COMMAND"' ERR

foo

echo "never going to happen"

Will output:

Hey I'm inside foo and will return 123
From lineno: 15 exiting with code 123 (last command was: return 123)

Note that trapping ERR might catch more stuff than you want...

Alternatively, you could trap EXIT (and set -e), but I wouldn't do that (set -e is controversial and has caveats).

Mangled Deutz
  • 11,384
  • 6
  • 39
  • 35
-1

Assuming you only care about capturing the exit status of a function, rather than using a trap you might consider using a wrapper function :

$ trace_function() {
  local result
  $@
  result=$?
  echo "$1 completed with status $result"
}

$ trace_function false
>false completed with status 1

$ trace_function true
>true completed with status 0

$ your_own_function() {
    if [ "$RANDOM" -gt "$1" ]; then
      echo ok
      return 0
    else
      echo ko
      return 1
    fi
}

$ trace_function your_own_function 16384
>ko
>your_own_function completed with status 1

$ trace_function your_own_function 16384
>ok
>your_own_function completed with status 0
Aaron
  • 24,009
  • 2
  • 33
  • 57
  • It needs to be trap. – Stefan Thorpe May 09 '19 at 10:23
  • @StefanThorpe I don't think it's possible to retrieve the exit code of a function using traps. At best you could trap ERR before calling the function to know if it returns a non-zero exit code. Could you maybe explain why using a wrapper function doesn't work for you? There may be yet another alternative which would suit you – Aaron May 09 '19 at 10:32
  • Because it's hundreds of functions, that are already wrapping. – Stefan Thorpe May 09 '19 at 14:59