(PE-3657) Call service stop functions after exception from init/start

Prior to this branch, if a Trapperkeeper service were to allow an
exception thrown during execution of its init or start function to
bubble up to the Trapperkeeper framework, the framework would never call
any stop functions in the services.  Services would not, therefore, have
a chance to clean up any resources that may have been created before the
initial exception was thrown.  If the resources created included worker
threads, for example, those threads could not be cleaned up -- leaving
the JVM process in a *zombie-like* state.

With changes in this branch, stop functions on services would be called
even if an exception had bubbled up to the framework during execution of
a service's init or start function.

This branch includes a new function on the shutdown service,
`get-shutdown-reason`, which can be used to get the current shutdown
reason (if one exists) without blocking the current thread until the
reason promise is realized.  The internal `get-app-shutdown-reason`
function provides a way to get at this new function via a handle to the
TrapperkeeperApp.

This branch includes changes to the bootstrap testutil functions,
which now make use of the current shutdown reason to translate a failure
to bootstrap without encountering an error into an exception thrown up
the stack.  The bootstrap testutil functions also include overloads with
an optional boolean argument which controls whether or not the failure
to bootstrap should result in the TrapperkeeperApp instance being
returned to the caller (true) vs. an exception being thrown (false, and
the default value).

This branch also updates the "reloaded" REPL example in the README.md
to show how to translate an error which had occurred in a `shutdown-on-error`
or `request-shutdown` into an exception, for ease in identifying that a service
error has occurred during startup.

There is a breaking change with this commit.  The `boot-*` functions
(e.g., `boot-with-cli-data`, `boot-services-with-cli-data`,
and `boot-services-with-config`) as well as the `build-app` function on
the `TrapperkeeperApp` instance would now swallow any exceptions
generated which had occurred during an init or start function call in a
service.  The only way to determine if a problem had occurred during
execution of the boot sequence would be to call the
`get-app-shutdown-reason` method upon completion of the bootstrap
process or call `run-app` to let the framework detect and act on the error.