[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

IRB, Mac OS X, command-line require via "-r" and Bus Errors

james.adam

5/16/2005 11:15:00 AM

Hey All,

I just wanted to put this out there and see firstly if anyone has
experienced the same problem, and secondly maybe someone has some ideas
as to how to go about fixing it.

I've posted some stuff mentioning this problem with Ruby-ODBC, the
Ruby-OpenGL module, and Timothy Hunter has also noticed it with RMagick
(http://www.codecomments.com/message4...). My current problem is
with the ruby-odbc module on Tiger with Ruby 1.8.2 (self-compiled,
although the problem exists with rubys compiled via fink, darwinports
and Apple). I have also seen this in the past (on Panther, too) when I
did some work to compile OpenGL on the mac using native frameworks, and
a similar problem has been hinted at with RubyCocoa and IRB
(http://rubycocoa.sourceforge.net/doc/programming.en.ht...).

The problem is *only* present when requiring the library from the
command-line, and not once IRB has loaded, i.e.

$ irb -r odbc
==> bus error

...but...

$ irb
irb(main):0> require 'odbc'
==> true

I'm confident that you can substitute "opengl", "rmagick", or maybe
even rubycocoa for odbc wherever I use it below. It gets worse. I then
added the following to my .irbrc file:

IRB.conf[:LOAD_MODULES] << "odbc"

... which basically adds the ODBC module to the array used to determine
which modules IRB should load. Now, ODBC gets loaded automatically into
IRB, without needing to be specified, i.e.:

$ irb
irb(main):0> puts ODBC.class
==> Module

Which means that it loaded fine! Here's why this is very strange - you
can trace the execution within IRB to get to this point as follows:

/usr/local/bin/irb
/usr/local/lib/ruby/1.8/irb.rb (IRB.start, around line 50)
/usr/local/lib/ruby/1.8/irb/init.rb (IRB.setup, at the top)

In IRB.setup, a bunch of stuff happens, including parsing the
command-line options and adding anything after a "-r" to
@CONF[:LOAD_MODULES] (IRB.parse_opts), and then finally taking each
string in that Array and loading each module (IRB.load_modules, at the
bottom of init.rb).

So what I can tell from this is that at the point where the module is
actually loaded (IRB.load_modules) adding a module to the @CONF
structure has resulted in exactly the same situation as having
specified it with "-r" on the command line. The @CONF[:LOAD_MODULES]
array is in exactly the same state if you specify modules in .irbrc as
it is if you require them with "-r" on the command line, and yet one
method works, and the other fails. Very, very strange.

BUT - here's where it gets TRULY weird. Keep this line in .irbrc, so
the offending module will be loaded. Next, in /usr/local/bin/irb,
immediately after the #! line, add this:

ARGV.clear

.... so basically I'm nuking ANY command-line arguments at all. Watch
and be amazed:

$ irb
irb(main):0> puts ODBC.class
==> Module
irb(main):1> exit
$ irb a_nonsense_argument_that_will_get_cleared_anyway
..... Bus Error.

It basically looks like having ANYTHING as a command line argument,
even if IRB doesn't do anything with that data (remember, the ARGV
array gets wiped immediately so IRB.parse_opts doesn't do anything), we
still get a bus error.

You can replicate this effect without even clearing ARGV. Try this:

$ irb -I .

.... it should crash too. I'm at the end of my tether, and can only see
this as being a bug in Mac OS X. However, I can't even find a reference
for memcmp in __CFInitialize (see
http://darwinsource.opendarwin.org/10.4/CF-368/Base.subproj/C...,
the Darwin source for Tiger). I am totally stumped.

Anyway, if ANYONE has got anything that might enlighten me, please
please let me know.

- James

21 Answers

lucsky

5/16/2005 11:53:00 AM

0

James Adam <james.adam@gmail.com> wrote:

> I just wanted to put this out there and see firstly if anyone has
> experienced the same problem, and secondly maybe someone has some ideas
> as to how to go about fixing it.

I've been tracking this down to the same level as you did, and just like
you I am stumped by the __CFInitialize stack trace (which ends up in
'bcmp' here, not in 'memcmp' btw).

I just hope that the 10.4.1 update will fix this, it's really annoying.

--
Luc Heinrich - lucsky@mac.com

james.adam

5/16/2005 1:15:00 PM

0

I'm not sure it's going to have much to do with anything new in
10.4.1... just because I've seen this happen in Panther too and it
wasn't fixed in any update or Tiger. Still, I hope at least for some
enlightenment! It's the most bizzare bug/code interaction I've ever
come across in 10 years of programming

- J

lucsky

5/17/2005 6:10:00 AM

0

James Adam <james.adam@gmail.com> wrote:

> I'm not sure it's going to have much to do with anything new in
> 10.4.1...

Right, I have just installed 10.4.1 (which is now available) the crash
still occurs.

--
Luc Heinrich - lucsky@mac.com

lucsky

5/17/2005 11:45:00 AM

0

James Adam <james.adam@gmail.com> wrote:

> I'm at the end of my tether, and can only see
> this as being a bug in Mac OS X. However, I can't even find a reference
> for memcmp in __CFInitialize (see
> http://darwinsource.opendarwin.org/10.4/CF-368/Base.subproj/C...,
> the Darwin source for Tiger).

Allright, here's some more data.

As already shown, this happens when calling irb with a request to load a
compiled extension through the '-r' option. *Any* compiled extension. So
to track this problem down a little bit more I created a simple dummy
extension but linked with the debug version of the CoreFoundation
framework, to hopefully be able to have more info in the stack trace.

Here's the code of the dummy extension.

## [begin test.c] ##

#include <ruby.h>
void Init_test( void )
{
rb_define_module( "Test" );
}

## [end test.c] ##

And here is how it is being built on my machine:

gcc -fno-common -pipe -I. -I/opt/local/include -I/opt/local/lib/ruby/1.8/powerpc-darwin8.0.0 -I/opt/local/lib/ruby/1.8/powerpc-darwin8.0.0 -O -c test.c

cc -dynamic -bundle -undefined suppress -flat_namespace -L/opt/local/lib -lruby -ldl -lobjc -o test.bundle /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFound
ation_debug test.o

Now let's see what we get:

% irb
irb(main):001:0> require 'test'
2005-05-17 13:31:03.113 irb[2408] CFLog (0): Assertions enabled
=> true

Looks like it works and we have some debug messages coming from the
debug version of the CoreFoundation framework. Now let's see what the
crashing version gives us:

% irb -r test
../test.bundle: [BUG] Bus Error
ruby 1.8.2 (2004-12-25) [powerpc-darwin8.0.0]

As expected, but this time the stack trace is a little bit more explicit
(showing here only the relevant lines):

Thread 0 Crashed:
0 libSystem.B.dylib 0x900033c0 strcmp + 192
1 CoreFoundation_debug 0x004bbfc4 __CFInitialize+600 (CFRuntime.c:720)

Two things:
- The crashing memcmp/bcmp that we got before is actually an strcmp
(probably inlined in the non-debug version).
- This strcmp is called from CFRuntime.c *around* line 720.

"Around" line 720 and not "at" line 720 because it appears that the
CoreFoundation framework that ships with 0S X is a little bit different
than the one for which we can have the sources.

Now, if we look at CFRuntime.c and find the strcmp closest to line 720
we fine this block of code:

{
CFIndex idx, cnt;
char **args = *_NSGetArgv();
cnt = *_NSGetArgc();
for (idx = 1; idx < cnt - 1; idx++) {
if (0 == strcmp(args[idx], "-AppleLanguages")) {
CFIndex length = strlen(args[idx + 1]);
__CFAppleLanguages = malloc(length + 1);
memmove(__CFAppleLanguages, args[idx + 1], length + 1);
break;
}
}
}

And not so surprisingly, this block is noodling with command line
arguments. What we need to know now is WHY exactly does this strcmp
crash.

--
Luc Heinrich - lucsky@mac.com

James Gray

5/17/2005 12:59:00 PM

0

On May 17, 2005, at 1:10 AM, Luc Heinrich wrote:

> James Adam <james.adam@gmail.com> wrote:
>
>
>> I'm not sure it's going to have much to do with anything new in
>> 10.4.1...
>>
>
> Right, I have just installed 10.4.1 (which is now available) the crash
> still occurs.

Just FYI, my secret to OS X Ruby happiness was to build my own copy
in /usr/local/, then adjust my path so it comes up first. This gives
me Ruby exactly as I want it, I never have to fiddle with Apple's
version, upgrades don't break it, etc. To me, it's the only way to go.

James Edward Gray II



Jonathan Paisley

5/17/2005 1:06:00 PM

0

On Tue, 17 May 2005 14:44:41 +0200, Luc Heinrich wrote:

> CFIndex idx, cnt;
> char **args = *_NSGetArgv();
> cnt = *_NSGetArgc();
> for (idx = 1; idx < cnt - 1; idx++) {
> if (0 == strcmp(args[idx], "-AppleLanguages")) {
> CFIndex length = strlen(args[idx + 1]);
> __CFAppleLanguages = malloc(length + 1);
> memmove(__CFAppleLanguages, args[idx + 1], length + 1);
> break;
>
> And not so surprisingly, this block is noodling with command line
> arguments. What we need to know now is WHY exactly does this strcmp
> crash.

I've investigated this a bit more, after seeing your post which was very
useful.

The problem is that before the code above loads, the ruby interpreter has
changed the arguments array to contain just the name of the program. So,
for example, if you run something like this:

$ irb arg1 arg2

argv will contain, at startup, {"irb","arg1","arg2"}, with argc=3
Assigning to $0 in ruby sets argv[0] to whatever you're set $0 to, and
sets the rest of the arguments to NULL (see set_arg0 in ruby.c).

So, by the time the CFRuntime code executes, argv looks like this:
{"irb",NULL,NULL}. Since the code doesn't check for potentially NULL
entries, it crashes.

The quick-fix is to just disable the assignment to $0 in irb.rb - the
first line of IRB.start.

I've filed a bug report with Apple, number 4121317.

Thanks,
Jonathan

Gavin Kistner

5/17/2005 1:36:00 PM

0

On May 17, 2005, at 6:58 AM, James Edward Gray II wrote:
> Just FYI, my secret to OS X Ruby happiness was to build my own copy
> in /usr/local/, then adjust my path so it comes up first. This
> gives me Ruby exactly as I want it, I never have to fiddle with
> Apple's version, upgrades don't break it, etc. To me, it's the
> only way to go.

Amen to that. I did the same, and life has been quite happy for a
long time since.

lucsky

5/17/2005 3:51:00 PM

0

James Edward Gray II <james@grayproductions.net> wrote:

> Just FYI, my secret to OS X Ruby happiness was to build my own copy
> in /usr/local/, then adjust my path so it comes up first. This gives
> me Ruby exactly as I want it, I never have to fiddle with Apple's
> version, upgrades don't break it, etc. To me, it's the only way to go.

Oh, we do agree on this, that's also what I do, although I have started
to use DarwinPorts since Tiger instead of manually building from the
source tarball.

Are you saying that the crash does *not* occur on your machine with your
custom built ruby ? That would surprise me after what was already found.

--
Luc Heinrich - lucsky@mac.com

lucsky

5/17/2005 3:51:00 PM

0

Jonathan Paisley <jp-www@dcs.gla.ac.uk> wrote:

> The quick-fix is to just disable the assignment to $0 in irb.rb - the
> first line of IRB.start.
>
> I've filed a bug report with Apple, number 4121317.

Very interesting. So we now know exactly what happens and why it
happens. Cool :)

But whose bug is it, really ?

On one hand, I agree that checking for NULL values in argv should
probably be done in CFRuntime.c. But on the other hand, nullifying argv
entries in set_arg0 while keeping the argc value intact is really asking
for troubles don't you think ? :)

--
Luc Heinrich - lucsky@mac.com

James Gray

5/17/2005 4:05:00 PM

0

On May 17, 2005, at 10:55 AM, Luc Heinrich wrote:

> Are you saying that the crash does *not* occur on your machine with
> your
> custom built ruby ? That would surprise me after what was already
> found.

Oh no. Sorry if I implied that. I was just trying to be helpful in
a thread I haven't been following as closely as I should have before
posting. :)

James Edward Gray II