Skip to content

Cannot interrupt threads #943

@cosmos72

Description

@cosmos72

Version 10.0.0 added (thread-join) that waits for a thread to exit,
but there is no (thread-interrupt) or equivalent procedure to interrupt/terminate a thread created with (fork-thread).

This would be very useful, possibly together with a procedure that lists existing threads,
to have visibility and control on threads and their lifetime: it's similar in spirit to

  • a shell that can list the running jobs and send signals to them
  • a multiprocess system that can list the running processes and send signals to them

because at the moment threads are almost completely opaque:
there's no way to know which threads exist, and no way to manage them.

A short review of the situation in other Lisp dialects:


In Common Lisp, the de-facto standard library Bordeaux Threads has both features:

  • function (all-threads) to list existing threads
  • function (interrupt-thread) to interrupt a thread

Racket nowadays runs on top of Chez Scheme.
It uses the name place instead of thread and has two procedures for terminating them:
(place-kill) and (place-break) documented in https://docs.racket-lang.org/reference/places.html


In Chez Scheme <= 10.0.0, one could manually send a POSIX signal to a thread,
but version 10.1.0 essentially removes such ability, because signals are always forwarded
to the main thread - see #813 - to avoid crashes when a signal is sent to a GC thread.

This is unfortunate, because sending a POSIX signal to a thread was the simplest
and most direct mechanism to wake it from a blocking system call.

The current architecture can already execute Scheme code in reaction to a signal - see (register-signal-handler)
and a possibility would be to raise a condition from the registered Scheme signal handler,
since it unwinds the stack and runs the after thunk of each (dynamic-wind),
allowing a thread to cleanup its resources - acquired mutexes, etc - before exiting.


Proposal:

  • by default, block most/all signals in secondary threads using pthread_sigmask()
    this is needed to avoid regressions related to Intermittent crash in make test #809 and constrain signal delivery to Scheme to the main thread #813
  • update non-GC secondary threads to selectively unblock the signals they accept - for example at least SIGINT or similar
  • no longer ignore SIGINT in secondary threads - see handle_signal() in c/schsig.c
  • restore the ability to process POSIX signals in secondary threads, i.e. remove the section #ifdef PTHREADS ... #endif in forward_signal_to_scheme() in c/schsig.c
  • add a procedure (thread-interrupt thread) that sends SIGINT or similar to specified thread, by calling pthread_kill()
  • when creating a thread with (fork-thread), set (break-handler) to a procedure that raises a condition "thread interrupted" - (break-handler) is already invoked in reaction to SIGINT and there's no point in interacting with the user from a secondary thread.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions