It turns out that the breakpoint in question (2.1) was the All Exceptions breakpoint. The method I was calling raised an exception, which caused the All Exceptions breakpoint to be hit. po
will stop execution once a breakpoint is reached (see this answer for more info).
If you disable the All Exceptions breakpoint and run it again, it is more clear that there was an exception:
error: Execution was interrupted, reason: signal SIGSTOP.
The process has been returned to the state before execution.
If you always leave the All Exceptions breakpoint enabled, then the message can be ambiguous: did it reach a breakpoint because there really was a breakpoint somewhere along the execution path, or was an exception raised?
An alternative solution (which doesn't require disabling the All Exceptions breakpoint) is to use expr
instead of po
(see the link above for a description of the following flags).
Running expr -u 0 -o -- foo()
produces the following output:
error: Execution was interrupted, reason: breakpoint 2.1 -2.1.
The process has been left at the point where it was interrupted.
* thread #1: tid = [...] libobjc.A.dylib`objc_exception_throw, stop reason = breakpoint 2.1 -2.1
frame #0: [...] libobjc.A.dylib`objc_exception_throw
The objc_exception_throw
string is a hint that an exception was raised.