-----BEGIN PGP SIGNED MESSAGE-----
After some deep thought, I think I finally understand what the error
message “[BUG] cross-thread violation on rb_gc()” means. I will
present my understanding here; please correct me if I am wrong or
confirm if I am correct.
Suppose you have a C program which statically links with the Ruby
library and makes use of Ruby’s C API functions. In particular, the
C program creates some Ruby strings from C strings using
StringValueCStr() and puts them inside a Ruby array.
So far so good. Now suppose that the C program wants to run an
embedded Ruby interpreter in the “background” while it is doing
other things. The C program does this by wrapping the ruby_run()
function (which never returns) inside a pthread.
Let’s review the situation so far with a diagram:
Here we have the C program’s main() function running in the
foreground and the embedded Ruby interpreter running in the background.
Now, suppose the embedded Ruby interpreter inside ruby_run() invokes
the garbage collector by calling the rb_gc() function. What happens?
There are two situations:
- The garbage collector collects garbage created only by the
embedded Ruby interpreter inside ruby_run(). It ignores the garbage
created by the C program (remember that it created a Ruby array of
No problem here. The garbage collector frees up space for the
embedded Ruby interpreter and the interpreter merrily resumes
whatever it was doing.
- The garbage collector tries to collect the Ruby array of Ruby
strings created by the C program. But wait a minute… the C program
which created that garbage is running in a different thread than
the embedded Ruby interpreter inside ruby_run()!
So, the garbage collector emits this error message and terminates
the Ruby interpreter (ruby_run): “[BUG] cross-thread violation on
That’s my understanding of the error message. If I am correct, then
a solution to this problem would be to prohibit the C program from
using Ruby’s C API functions. That way, the C program never creates
any Ruby objects which can be garbage collected by the embedded Ruby
interpreter that runs inside another thread.
What do you think?
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v184.108.40.206 (GNU/Linux)
-----END PGP SIGNATURE-----