A break is an asynchronous exception, usually triggered by an external source controlled by the user. A break exception can only occur in a thread while breaks are allowed by the break-enabled parameter (see section 184.108.40.206). When a break is detected, the exn:misc:user-break exception is raised.
A break is triggered when the break-thread procedure is applied to a thread. An exn:misc:user-break is raised in the destination thread sometime afterwards; if breaking is disabled when break-thread is called, the break is suspended until breaking is again enabled for the thread. While a thread has a suspended break, additional breaks are ignored.
When break-thread is applied to a thread that is blocked on a nested thread (see call-in-nested-thread), and if breaks are enabled in the blocked thread, the break is implicitly handled by transferring it to the nested thread.
Breaks are disabled while an exception handler is executing. Note that the handling procedures supplied to with-handlers are not exception handlers, so breaking within such procedures is controlled by break-enabled.
Breaks are also disabled (independent of parameter settings) during the evaluation of the ``pre'' and ``post'' thunks for a dynamic-wind, whether called during the normal dynamic-wind calling sequence or via a continuation jump.
When breaks are enabled, they can occur at any point within execution, which makes certain implementation tasks subtle. For example, assuming breaks are enabled when the following code is executed,
(with-handlers ([exn:user:break? (lambda (x) (void))]) (semaphore-wait s))then it is not the case that a void result means the semaphore was decremented or a break was received, exclusively. It is possible that both occur: the break may occur after the semaphore is sucessfully decremented but before a void result is returned by semaphore-wait. A break exception will never demanage a semaphore, or any other built-in construct, but many built-in procedures (including semaphore-wait) contain internal sub-expressions that can be interrupted by a break.
In general, it is impossible using only semaphore-wait to implement the guarantee that either the semaphore is deceremented or an exception is raised, but not both. MzScheme therefore supplies semaphore-wait/enable-break (see section 9.2), which does permit the implementation of such an exclusive guarantee:
(parameterize ([break-enabled #f]) (with-handlers ([exn:user:break? (lambda (x) (void))]) (semaphore-wait/enable-break s)))In the above expression, a break can occur at any point until break are disabled, in which case a break exception is propagated to the enclosing exception handler. Otherwise, the break can only occur within semaphore-wait/enable-break, which guarantees that if a break excpetion is raised, the semaphore will not have been decremented.
To allow similar implementation patterns over blocking port operations, MzScheme provides the read-string-avail!/enable-break and write-string-avail/enable-break procedures (see section 11.1.7).