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.
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 canceling 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 asynchronous 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.
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.
void *
scm_c_call_with_blocked_asyncs (void * (*proc) (void *data), void *data)
¶The same but with a C function proc instead of a Scheme thunk.
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.
void *
scm_c_call_with_unblocked_asyncs (void *(*proc) (void *data), void *data)
¶The same but with a C function proc instead of a Scheme thunk.
void
scm_dynwind_block_asyncs ()
¶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).
void
scm_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:
int
scm_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 signaled 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.
int
scm_c_prepare_to_wait_on_cond (scm_i_pthread_mutex_t *mutex, scm_i_pthread_cond_t *cond)
¶Inform Guile that the current thread is about to sleep, and that if an
asynchronous interrupt is signaled on this thread, Guile should wake up
the thread by acquiring mutex and signaling 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.
void
scm_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.