"undefined method `synchronize' for #<Mutex:0xa0f5adc>" from embedded Ruby program

I’m writing a C++ program (on Centos 5 Linux) that embeds a Ruby 1.9.3
p327 interpreter. It mostly works, but I’m getting a strange error from
a script called by the program. When run from the command line (i.e. not
embedded), the script works correctly. The error is:
undefined method `synchronize’ for #Mutex:0xa0f5adc
If I search back over this list’s archives, I can see a few other people
with the same problem (but no solution).

I’ve narrowed it down to the following test program:

#include <ruby.h>

int
main(int argc, char *argv[])
{
RUBY_INIT_STACK;
ruby_init();
ruby_init_loadpath();

rb_eval_string("$mutex = Mutex.new");
rb_eval_string("$mutex.synchronize(){}");

return 0;

}

Does anybody have any clues, please?

Thanks, Graham

Is this thread related?

http://www.ruby-forum.com/topic/217934

On 21 November 2012 16:38, Graham Menhennitt
[email protected]wrote:

#include <ruby.h>

return 0;

}

Does anybody have any clues, please?

Thanks, Graham


Matthew K., B.Sc (CompSci) (Hons)
http://matthew.kerwin.net.au/
ABN: 59-013-727-651

“You’ll never find a programming language that frees
you from the burden of clarifying your ideas.” - xkcd

On 21/11/2012 17:46, Matthew K. wrote:

from
a script called by the program. When run from the command line
(i.e. not
embedded), the script works correctly. The error is:
    undefined method `synchronize' for #<Mutex:0xa0f5adc>
If I search back over this list's archives, I can see a few other
people
with the same problem (but no solution).

Yes, that was one of the “few other people”. But no solution to it.

Thanks for replying,
Graham

On 21/11/2012 5:38 PM, Graham Menhennitt wrote:

 RUBY_INIT_STACK;
 ruby_init();
 ruby_init_loadpath();

 rb_eval_string("$mutex = Mutex.new");
 rb_eval_string("$mutex.synchronize(){}");

 return 0;

}

I’ve done a bit more investigation and found that it happens in all 1.9
releases of Ruby, but it does NOT happen in 1.8.7.

The test program below produces:

[:locked?, :try_lock, :lock, :unlock, :sleep, :nil?, :===, :=~, :!~,
:eql?, :hash, :<=>, :class, :singleton_class, :clone, :dup,
:initialize_dup, :initialize_clone, :taint, :tainted?, :untaint,
:untrust, :untrusted?, :trust, :freeze, :frozen?, :to_s, :inspect,
:methods, :singleton_methods, :protected_methods, :private_methods,
:public_methods, :instance_variables, :instance_variable_get,
:instance_variable_set, :instance_variable_defined?, :instance_of?,
:kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?,
:respond_to_missing?, :extend, :display, :method, :public_method,
:define_singleton_method, :object_id, :to_enum, :enum_for, :==,
:equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, 

:id]

Whereas running “ruby -e ‘p Mutex.new.methods’” produces:

[:locked?, :try_lock, :lock, :unlock, :sleep, :synchronize, :nil?,
:===, :=~, :!~, :eql?, :hash, :<=>, :class, :singleton_class,
:clone, :dup, :initialize_dup, :initialize_clone, :taint, :tainted?,
:untaint, :untrust, :untrusted?, :trust, :freeze, :frozen?, :to_s,
:inspect, :methods, :singleton_methods, :protected_methods,
:private_methods, :public_methods, :instance_variables,
:instance_variable_get, :instance_variable_set,
:instance_variable_defined?, :instance_of?, :kind_of?, :is_a?, :tap,
:send, :public_send, :respond_to?, :respond_to_missing?, :extend,
:display, :method, :public_method, :define_singleton_method,
:object_id, :to_enum, :enum_for, :==, :equal?, :!, :!=,
:instance_eval, :instance_exec, :__send__, :__id__]

Note that “:synchronize” is missing from the former.

I’ve tried removing all gems in case one of them was doing something
strange. I’ve searched the Ruby source code, but I can’t see anything
that might cause this.

Anybody got any ideas? Should I take this to ruby.core?

Thanks,
Graham

Test program:

#include <ruby.h>

int
main(int argc, char *argv[])
{
     RUBY_INIT_STACK;
     ruby_init();
     ruby_init_loadpath();

     rb_eval_string("p Mutex.new.methods");

     return 0;
}

I’ve tried removing all gems in case one of them was doing something strange.
I’ve searched the Ruby source code, but I can’t see anything that might cause
this.
I can’t even locate where the Mutex class gets “synchronize” added as a
method to it. thread.c defines rb_mutex_synchronize, but Init_Thread
therein doesn’t appear to add it as a method on rb_cMutex.

I note that:

Mutex.new.method(:lock).source_location => nil
(2345).method(:to_s).source_location => nil

Yet:

Mutex.new.method(:synchronize).source_location => [“internal:prelude”,
7]

So it’s definitely special-cased in a way that may be affecting your
ability to access it.

Arlen

Ah: prelude.rb defines Mutex#synchronize and Thread.exclusive in Ruby.

prelude.rb is called by Init_prelude(), generated by
tool/compile_prelude.rb, itself called by ruby_init_prelude() (in
ruby.c).

That in turn is called by ruby_process_options() (in ruby.c) which is
called by ruby_options() (from eval.c). It’s up to you which of the
various ones you want to use, but ruby_init() followed by
rb_eval_string() will leave you with a probably incomplete environment.

You’re already calling ruby_init_loadpath() yourself, for example, which
would normally be done for you by ruby_process_options().

(You could try the hacky method of calling ruby_init_prelude() yourself,
too.)

Arlen

On 22/11/2012 1:09 PM, Arlen C. wrote:

Thanks for replying, Arlen.

I added a call to ruby_init_prelude() but it isn’t declared in ruby.h so
I got a compilation error. I tried declaring it myself, but then it
won’t link because it’s static in ruby.c.

I then tried calling ruby_process_options(int argc, char**argv). The
first time I called it as ruby_process_options(0, 0). That causes a SEGV
since it dereferences argv[0] even though argc is zero. This is arguably
a bug, but anyway…

Next I called it with real argc and argv parameters with argc set to one

  • it hung reading from standard input (equivalent to just typing “ruby”
    at a shell prompt).

Finally, I faked the arguments as “ruby /dev/null” and it worked!!! I
now get synchronized() defined. It’s a bit clumsy having to fake the
arguments, but beggars can’t be choosers.

I’ll go back to my original script and see whether it works… Yes it
does!

Thanks very much for your assistance,
Graham

Hi Graham,

I added a call to ruby_init_prelude() but it isn’t declared in ruby.h so
I got a compilation error. I tried declaring it myself, but then it
won’t link because it’s static in ruby.c.

My bad—I didn’t think to check the linkage; was assuming the ruby_
prefix implied it might be externally called.

Finally, I faked the arguments as “ruby /dev/null” and it worked!!! I
now get synchronized() defined. It’s a bit clumsy having to fake the
arguments, but beggars can’t be choosers.

It does seem like a less than perfect solution. :frowning: I note (re: your
comment that derefing argv when argc==0 is probably a bug) that the
offending line does have that somewhat cheeky comment, /* for the time
being */.

I’ll go back to my original script and see whether it works… Yes it does!
Great! Super glad this has worked out well. :slight_smile:

Cheers,

Arlen

On 22/11/2012 2:07 PM, Arlen C. wrote:

It does seem like a less than perfect solution. :frowning: I note (re: your
comment that derefing argv when argc==0 is probably a bug) that the
offending line does have that somewhat cheeky comment, /* for the time
being */.
Yes, I saw that too - I’ll file a defect against it. I’ll also file one
about having to do the fake argc/argv.

Anyway, just for completeness and for anybody else looking for a
workaround, here is my working test program.

Graham

#include <ruby.h>

int
main(int argc, char *argv[])
{
     RUBY_INIT_STACK;
     ruby_init();
     static char* args[] = { "ruby", "/dev/null" };
     ruby_process_options(2, args);

     rb_eval_string("p Mutex.new.methods");

     return 0;
}