Re-reading my post, I have a hunch as to what might be happening.

When it hits the trap, it must be executing the trap's "exit 1" in the context of the parent function "TestForBadProblem" instead of in the context of the main top level script.

I may have to define a second trap that invokes the first trap.

EDIT: No, that didn't work. Here's my updated code and output:

Code:
#!/bin/bash

# ----------------------------------------------
# Bash - How to fully exit a program from within
# a function which returns data to the caller.
# ----------------------------------------------
# Program to demonstrate an issue with Bash.
# The problem is: You want to write a function
# which can either:
#   - Return data to the caller.
#   - Or exit the script completely if it
#     discovers some kind of a problem.
# The problem is that Bash can't do both. You can
# only exit the script if you are at the top level
# or from inside a function where the call to the
# function doesn't try to retrieve data from it.
# You can't do variable=$(function) where the
# function wants to maybe exit the script.
# This program demonstrates the problem and the
# work-around.

# ----------------------------------------------
# Work-around is here
# ----------------------------------------------
# These two lines are part of a work-around to the
# problem that this program demonstrates. This
# was obtained from the following StackOverflow
# question:
# https://stackoverflow.com/questions/9893667/is-there-a-way-to-write-a-bash-function-which-aborts-the-whole-execution-no-mat
trap "exit 1" TERM
export TOP_PID=$$
# Combine it with "kill -s TERM $TOP_PID" inside
# the function where you want to exit the program. 


# ----------------------------------------------
# Function: Test for a problem. If there is no
# problem, then gather some data and return it.
# If there is a problem, exit the program.
# ----------------------------------------------
TestForBadProblem()
{
  trap "kill -s TERM $TOP_PID" TERM
  export SUB_PID=$$
  
  echo "Testing for a potential bad problem..."  >&2
  if "$badProblem" = true
  then
    echo "There was a bad problem. Exiting program now." >&2

    # ----------------------------------------------
    # BUG IS DEMONSTRATED HERE
    # ----------------------------------------------
    # The goal is to exit the script at this point,
    # but in this spot it will not work as expected
    # in every case, it will not always exit the 
    # script. TO DEMONSTRATE THE PROBLEM, UNCOMMENT
    # THIS LINE OF THE SCRIPT AND RUN IT.
    #   exit 1
    # Instead, to fix the problem, invoke the special
    # trap (created above) to exit the script at the
    # main level instead of from within this lower
    # level function. Here is the work-around:
    kill -s TERM $TOP_PID
    # That line combined with the trap above, works
    # around the problem.
  else
    echo "No bad problem found." >&2
  fi

  # New test: Additional test to see if the workaround
  # succeeds in a sub-sub routine.
  returnFromSubTest=$( SubTestForProblem )

  if "$subProblem" = true
  then
    echo "----------------------------------------------------------------" >&2
    echo "BUG: This line should not be reached, program should have exited." >&2
    echo "Returned data from Sub Test is $returnFromSubTest." >&2
    echo "----------------------------------------------------------------" >&2  
  fi

  echo "Returning data from function." >&2
  returnData="Some_Data"
  echo $returnData
}


# ----------------------------------------------
# Function: SUBTEST for a problem and kill the
# program if there is a problem. This will be
# called as a sub-sub-routine from the 
# TestForBadProblem function.
# ----------------------------------------------
SubTestForProblem()
{
  echo "SubTesting Now (subroutine from subroutine)..."  >&2
  if "$subProblem" = true
  then
    # If the work-around is working as I expect it to work,
    # the program should be killed here just as effectively
    # as if I had killed it from the parent function. But
    # it's not quite doing that. It seems to complete the
    # parent function before killing the program.
    echo "There was a subtest problem. Exiting program." >&2
    kill -s TERM $SUB_PID
  else
    echo "No sub problem found. Returning data" >&2
  fi
  
  subReturnData="Some_Sub_Data"
  echo $subReturnData
}


# ----------------------------------------------
# Main program code body
# ----------------------------------------------
echo "Starting program now."  >&2

# ----------------------------------------------
# First test - There should be no problem and it
# should return data from the function.
# ----------------------------------------------
echo "" >&2
echo "First test - No problem encountered, data retrieved." >&2
badProblem=false
subProblem=false
returnedData=$( TestForBadProblem )
echo "returnedData was: $returnedData" >&2

# ----------------------------------------------
# Test 1.5 - Try a sub-function
# ----------------------------------------------
echo "" >&2
echo "1.5 test - Only subProblem encountered, data retrieved." >&2
badProblem=false
subProblem=true
returnedData=$( TestForBadProblem )
echo "returnedData was: $returnedData" >&2

# ----------------------------------------------
# Second test - There should be a bad problem
# encountered and it should quit the program
# without trying to return any data at all.
# It shouldn't even reach the line that tries
# to echo the returned data.
# ----------------------------------------------
echo "" >&2
echo "Second test - Problem encountered, attempt to retrieve data, method 1." >&2
badProblem=true
subProblem=false
returnedData=$( TestForBadProblem )
echo "returnedData was: $returnedData" >&2

# ----------------------------------------------
# You should not reach this line of code because
# the program should have exited in the second
# test. However the program continues to this
# point, despite the documentation for "exit"
# indicating that it should truly exit rather
# than just act like a "return" statement.
# ----------------------------------------------
echo "" >&2
echo "----------------------------------------------------------------" >&2
echo "BUG: If you can read this, the program did not exit as expected." >&2
echo "----------------------------------------------------------------" >&2

# ----------------------------------------------
# Third test. Try a different way of reading the
# function's return data. This does not work, it
# just sets a string value rather than calling
# the function. The function never gets called.
# ----------------------------------------------
echo "" >&2
echo "Third test - Attempt to retrieve data, method 2." >&2
badProblem=true
subProblem=false
returnedData=TestForBadProblem
echo "returnedData was: $returnedData" >&2

# ----------------------------------------------
# Last test - Call the function but without
# trying to read any return data from it. This
# works as expected, but I want to read the data
# so I can't use this method.
# ----------------------------------------------
echo "" >&2
echo "Last test - Problem encountered, do not attempt to retrieve data." >&2
badProblem=true
subProblem=false
TestForBadProblem
echo "Program will not reach this line, you will not see it." >&2


Code:
Starting program now.

First test - No problem encountered, data retrieved.
Testing for a potential bad problem...
No bad problem found.
SubTesting Now (subroutine from subroutine)...
No sub problem found. Returning data
Returning data from function.
returnedData was: Some_Data

1.5 test - Only subProblem encountered, data retrieved.
Testing for a potential bad problem...
No bad problem found.
SubTesting Now (subroutine from subroutine)...
There was a subtest problem. Exiting program.
----------------------------------------------------------------
BUG: This line should not be reached, program should have exited.
Returned data from Sub Test is Some_Sub_Data.
----------------------------------------------------------------
Returning data from function.
_________________________
Tony Fabris