In functional languages, generally the value of the body of the function specifies what is returned.
In imperative languages, it's more common to have a explicit "return()"; some languages allow the function to specify its return value by either allowing an assignment to the function's name, or having some syntax to specify a special name to refer to the value of a function.
Exceptions are unexpected/unusual situations that are not easily handled locally. Run-time errors, particularly those related to I/O, are often awkward at the point of contact, and often are more cleanly handled elsewhere. If the elsewhere is up the stack in a parent activation record, then the stack needs to be unwound to that point.
Unwinding means not only popping off all those activation frames, but also restoring the state at the point of recovery in the propagation process.
These are pretty rare; I don't remember ever seeing these actually used anywhere (well, that is outside of assembly language; co-routines are trivial in assembly language), though apparently some languages do like to use these to implement iterators.
As your text notes, threads are quite similar in many ways, and offer more functionality at a very modest price.