A question about callbacks from a C library, where the callback will be initiated from a OS thread.
I'd like to initiate a callback as a kind of signal from a C library.
The signal will carry one integer value.
The callback function will be registered from racket and the call to the callback function will be done from a thread started by the C library.
I've read the FFI manual, but I'm not sure what to do.
As I understand it, the callback can be called in 'atomic' mode.
I should not use semaphore-post there.
The signal signals that data is waiting to be retrieved from de C library.
So I would like to have a racket thread, waiting on a semaphore or mutex and in the callback function I'd like to post the semaphore or unlock the mutex, so that data will be retrieved without polling.
I'm not sure how to do this. Had several crashes.
Does anyone have a hint?
I’ve been thinking. Would an async-apply combined with atomic? #t and in the callback, using a put on an async os channel be enough, while using sync in a racket thread?
From my reading of the docs, you definitely need an async-apply. I would try #:async-apply (lambda (p) (p)) first; that might be sufficient. You also need to make sure the closure doesn't get collected by the GC; that's a likely cause of crashes. Calling semaphore-post in atomic mode should be fine (semaphore-wait is not, of course).
Here's a little example program that waits until it receives either SIGUSR1 or SIGUSR2 (tested on Linux x86-64; should work on Mac OS too but the signal numbers might be different):
Run this program in one terminal, then run kill -s SIGUSR2 $pid (with the pid of the Racket process) in another. The first program should print 12 and terminate.
Using the commented-out calls to signal instead will likely crash because the anonymous closures get garbage collected. A fix would be to use #:keep to make sure they don't get collected before you're done with them. For example, you could replace the beginning of the program with the following: