Skip to content

Instantly share code, notes, and snippets.

@chrismcg
Created July 25, 2008 17:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chrismcg/2476 to your computer and use it in GitHub Desktop.
Save chrismcg/2476 to your computer and use it in GitHub Desktop.
/* Ruby Thread support:
Ruby implements threads by using setjmp/longjmp to switch between separate
C stacks within one native thread.
This confuses Objective C because NSThread stores a per-native-thread stack
of autorelease pools and exception handlers. When the C stack changes, an
error message like this is likely to appear:
Exception handlers were not properly removed. Some code has jumped or
returned out of an NS_DURING...NS_HANDLER region without using the
NS_VOIDRETURN or NS_VALUERETURN macros
The semantics of NSAutoreleasePools are also broken because the effective
scope crosses multiple threads.
The solution below requires a patch to the Ruby interpreter that implements
the following function:
void rb_add_threadswitch_hook(rb_threadswitch_hook_func_t func)
A hook is registered that multiplexes sets of autorelease pools and
exception stacks onto one NSThread.
Whenever a Ruby thread is switched in or out, the relevant context is saved
and restored.
Unfortunately, implementing this requires fiddling with two fields in the
NSThread internal structure.
A further complication arises due to the dynamic linker. Suppose RubyCocoa
has been linked against a patched libruby, but at runtime the user
accidentally uses /usr/bin/ruby (unpatched) to load RubyCocoa. Since
/usr/bin/ruby links to /usr/lib/libruby.dylib, and RubyCocoa links to
/path/to/patched/libruby.dylib, most of the functions will be picked up
from /usr/lib/libruby.dylib, but rb_add_threadswitch_hook will be linked
from the patched libruby.dylib.
The setup code explicitly determines the name of the libraries from which
two relevant symbols have been loaded from, and issues a warning and aborts
the setup process if they are different.
Tested on 10.4.7 PowerPC.
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment