6.22.3 Asynchronous Interrupts

Every Guile thread can be interrupted. Threads running Guile code will
periodically check if there are pending interrupts and run them if
necessary. To interrupt a thread, call system-async-mark on that
thread.

Scheme Procedure: system-async-markproc [thread]

C Function: scm_system_async_mark(proc)

C Function: scm_system_async_mark_for_thread(proc, thread)

Enqueue proc (a procedure with zero arguments) for future
execution in thread. When proc has already been enqueued
for thread but has not been executed yet, this call has no effect.
When thread is omitted, the thread that called
system-async-mark is used.

Note that scm_system_async_mark_for_thread is not
“async-signal-safe” and so cannot be called from a C signal handler.
(Indeed in general, libguile functions are not safe to call from
C signal handlers.)

Though an interrupt procedure can have any side effect permitted to
Guile code, asynchronous interrupts are generally used either for
profiling or for prematurely cancelling a computation. The former case
is mostly transparent to the program being run, by design, but the
latter case can introduce bugs. Like finalizers (see Foreign Object Memory Management), asynchronous interrupts introduce concurrency in a
program. An asyncronous interrupt can run in the middle of some
mutex-protected operation, for example, and potentially corrupt the
program’s state.

If some bit of Guile code needs to temporarily inhibit interrupts, it
can use call-with-blocked-asyncs. This function works by
temporarily increasing the async blocking level of the current
thread while a given procedure is running. The blocking level starts
out at zero, and whenever a safe point is reached, a blocking level
greater than zero will prevent the execution of queued asyncs.

Analogously, the procedure call-with-unblocked-asyncs will
temporarily decrease the blocking level of the current thread. You
can use it when you want to disable asyncs by default and only allow
them temporarily.

In addition to the C versions of call-with-blocked-asyncs and
call-with-unblocked-asyncs, C code can use
scm_dynwind_block_asyncs and scm_dynwind_unblock_asyncs
inside a dynamic context (see Dynamic Wind) to block or
unblock asyncs temporarily.

Scheme Procedure: call-with-blocked-asyncsproc

C Function: scm_call_with_blocked_asyncs(proc)

Call proc and block the execution of asyncs by one level for the
current thread while it is running. Return the value returned by
proc. For the first two variants, call proc with no
arguments; for the third, call it with data.

Call proc and unblock the execution of asyncs by one level for the
current thread while it is running. Return the value returned by
proc. For the first two variants, call proc with no
arguments; for the third, call it with data.

During the current dynwind context, increase the blocking of asyncs by
one level. This function must be used inside a pair of calls to
scm_dynwind_begin and scm_dynwind_end (see Dynamic Wind).

C Function: voidscm_dynwind_unblock_asyncs()

During the current dynwind context, decrease the blocking of asyncs by
one level. This function must be used inside a pair of calls to
scm_dynwind_begin and scm_dynwind_end (see Dynamic Wind).

Sometimes you want to interrupt a thread that might be waiting for
something to happen, for example on a file descriptor or a condition
variable. In that case you can inform Guile of how to interrupt that
wait using the following procedures:

C Function: intscm_c_prepare_to_wait_on_fd(int fd)

Inform Guile that the current thread is about to sleep, and that if an
asynchronous interrupt is signalled on this thread, Guile should wake up
the thread by writing a zero byte to fd. Returns zero if the
prepare succeeded, or nonzero if the thread already has a pending async
and that it should avoid waiting.

Inform Guile that the current thread is about to sleep, and that if an
asynchronous interrupt is signalled on this thread, Guile should wake up
the thread by acquiring mutex and signalling cond. The
caller must already hold mutex and only drop it as part of the
pthread_cond_wait call. Returns zero if the prepare succeeded,
or nonzero if the thread already has a pending async and that it should
avoid waiting.

C Function: voidscm_c_wait_finished(void)

Inform Guile that the current thread has finished waiting, and that
asynchronous interrupts no longer need any special wakeup action; the
current thread will periodically poll its internal queue instead.

Guile’s own interface to sleep, wait-condition-variable,
select, and so on all call the above routines as appropriate.

Finally, note that threads can also be interrupted via POSIX signals.
See Signals. As an implementation detail, signal handlers will
effectively call system-async-mark in a signal-safe way,
eventually running the signal handler using the same async mechanism.
In this way you can temporarily inhibit signal handlers from running
using the above interfaces.