Next: Error Escape Handler Up: Exceptions and Control Flow Previous: Continuation Marks

# Breaks

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 9.4.1.10). 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).

Next: Error Escape Handler Up: Exceptions and Control Flow Previous: Continuation Marks