Jonathan Paisley
jp-ww****@dcs*****
Thu Aug 24 07:08:20 JST 2006
Hi all, I've attached to this message the latest update to my Ruby Thread patches for RubyCocoa. The patches come in two parts: (1) ruby-thread-hooks.patch This is a patch to the 1.8.5pre interpreter (also should work on 1.8.4) that adds an exported function called 'rb_add_threadswitch_hook'. (2) rubycocoa-threads.patch This is a patch to RubyCocoa (apply to trunk with my xcodeproj updates) that adds the RubyCocoa code to talk to those patches. If the Ruby interpreter hasn't been patched, RubyCocoa should still build and work as it did before. Patch (2) overrides Thread.new to raise an exception if runtime thread support is not present. I've added a test file that exercises the code: test/tc_thread.rb. There are some comments in there that explain what it's doing, and you can try running the tests with a non-patched interpreter to see the nasty crashes that occur. I've pasted below an extracted comment from RBRuntime.m. Cheers, Jonathan /* 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. */ -------------- next part -------------- A non-text attachment was scrubbed... Name: ruby-thread-hooks.patch Type: application/octet-stream Size: 3322 bytes Desc: not available Url : http://lists.sourceforge.jp/mailman/archives/rubycocoa-devel/attachments/20060823/eb80d7b3/attachment.obj -------------- next part -------------- A non-text attachment was scrubbed... Name: rubycocoa-threads.patch Type: application/octet-stream Size: 26262 bytes Desc: not available Url : http://lists.sourceforge.jp/mailman/archives/rubycocoa-devel/attachments/20060823/eb80d7b3/attachment-0001.obj