With stuff like gstreamer it’s possible that signals originate from
threads that are different from ruby’s native thread.
Currently the signal marshaller always enters the ruby interpreter to
signals even if it’s not run in ruby’s native thread. Leading to all
The following patch solves this as follows:
On intialization it creates a pipe and a ruby thread watching it
Now when a signal is marshalled in a non-native thread, the
puts all signal info in a shared variable and writes one byte
into the pipe. When the marshal_pop thread sees this, it will run
actuall callback in ruby’s native thread. Obviously there is some
going on, see the code for more details.
Conceptually this means that the thread that emitted the signal and
native thread are temporary synchronized while the callback is run.
quite effectively fixes the crashes i’ve been seeing.
Note that this give some risk for deadlocks as the signal emition can
finish when the ruby thread can run (i.e. not while your waiting in
code). A good example of this is letting gstreamer wait on a state
for an element, while that state changes only happens after a certain
callback has been run…
I’ve also attached a small silly program (avtest) that crashes without
patch, but works fine with it.