|
From: | felix . winkelmann |
Subject: | [PATCH] thread-safe handling of asynchronous events |
Date: | Wed, 05 Jul 2023 15:28:54 +0200 |
Hello! Currently we have no thread-safe way of handling asynchronous events like POSIX signals and finalization. In both situations, the signal handler and finalization procedures are called in whatever thread is currently executing, which is a source of potential deadlocks in a multithreaded environment. One approach would be to have a dedicated thread for these events, but after studying existing APIs like Chez' "guardians" (for finalization) and the Racket signal interface, a "pull" interface that lets the user ask explicitly for such events appears to provide maximum control and still can be integrated into a threaded environment with relative ease. Therefore I provide 4 patches that implement an internal "event-queue" mechanism and revised finalization and signal API based on these queues. The basic principle is to associate a handler procedure with a queue of asynchronous events. Calling the handler retrieves events from the queue, either non-blocking or blocking. These events are not associated with a thread, but with a procedure, allowing the separation of the points in time when the event is triggered and the moment it is handled. The first patch provides the event-queue mechanism and cleans up the scheduler a bit (hiding internal variables while also exposing ##sys#... procedures to access them). This also defines hooks that a threading API should override to allow suspension/resumption on events. The second patch provides a new signal API: "make-signal-handler", which creates a handler for one or more signals and "signal-ignore" and "signal-default" (to ignore a signal or set the default disposition). This is roughly modelled after the Racket API. The old "signal-handler" and "set-signal-handler!" procedures have been deprecated. The third patch provides "make-finalizer", inspired by Chez' guardians, but slightly different to allow blocking/non-blocking tests for finalizations. The old API is still available, as often finalization performs only very basic operations independent of the currently executing context. Finalization procedures can be composed, as a finalizer itself becomes subject to finalization once all associated objects have been collected. Building guardians on top of this should be straightforward, but the latter does not (to my knowledge) allow blocking a thread until a finalizer triggers so I chose not to implement this interface. The fourth patch extends srfi-18 to set the hooks defined in the first patch. This patch uses some definitions from the scheduler.scm changes but does not directly depend on them (the hooks will never be invoked). Note that the basic C/Scheme glue for finalizers and signals has not been touched, these changes merely provide a different interface. The scheduler cleanup is only superficial and mostly for exposing whether threads are ready or waiting and to provide some syntactic consistency. I tried my best to split these changes into meaningful patches, but my relation to git is a troubled one, and the changes to NEWS are likely to result in conflicts anyway, so expect some fiddling. cheers, felix
0001-add-internal-event-queue-mechanism-and-hooks-for.patch
Description: Text Data
0002-Provide-new-thread-safe-API-for-POSIX-signals-deprec.patch
Description: Text document
0001-Added-thread-safe-finalization-method-make-finalizer.patch
Description: Text document
srfi-18.diff
Description: Text document
[Prev in Thread] | Current Thread | [Next in Thread] |