rb_eval_string blocks on loops even if run inside a thread.

I

Ian Leitch

[Note: parts of this message were removed to make it a legal post.]

Hey,

I'm trying to use rb_eval_string to execute a bunch of code and return from
it straight away. My problem is that the code I want to eval contains a
continuous loop. Even if I wrap the code in a thread the call still blocks
due to the loop. Note that I don't get the same behaviour when using eval()
outside of the C API.

E.g:

rb_eval_string("Thread.new { loop { puts 1; sleep 0.2 }}"); <-- blocks
eval("Thread.new { loop { puts 1; sleep 0.2 }}") <--- doesn't block

My guess is to spawn a ruby thread in C and call rb_eval_string inside that,
I can't find any examples of using the thread functions on google though so
I'm a bit stuck. Could someone give me a few pointers or perhaps some
example code?

Many thanks
Ian
 
B

brabuhr

I'm trying to use rb_eval_string to execute a bunch of code and return from
it straight away. My problem is that the code I want to eval contains a
continuous loop. Even if I wrap the code in a thread the call still blocks
due to the loop. Note that I don't get the same behaviour when using eval()
outside of the C API.

E.g:

rb_eval_string("Thread.new { loop { puts 1; sleep 0.2 }}"); <-- blocks
eval("Thread.new { loop { puts 1; sleep 0.2 }}") <--- doesn't block

My guess is to spawn a ruby thread in C and call rb_eval_string inside that,
I can't find any examples of using the thread functions on google though so
I'm a bit stuck. Could someone give me a few pointers or perhaps some
example code?

This is the first time I have ever tried embedding Ruby in C, but I
hope it helps. (The idea is to run ruby from a C thread so the rest
of your C program can maybe run in parallel):


#include <ruby.h>

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

void *do_ruby(void* param)
{
ruby_init();
rb_eval_string("loop { puts 'hello from ruby world'; sleep 5 }");
ruby_finalize();
}

int main(int argc, char *argv[])
{
pthread_t ruby_thread;

printf("BEFORE DO_RUBY\n");

pthread_create( &ruby_thread, NULL, do_ruby, NULL);

printf("AFTER DO_RUBY\n");

pthread_join(ruby_thread, NULL);

return 0;
}

gcc -o foo -lpthread -lruby1.8 -I/usr/lib/ruby/1.8/i486-linux foo.c
./foo
BEFORE DO_RUBY
hello from ruby world
AFTER DO_RUBY
hello from ruby world
hello from ruby world
^C(eval): (eval):0:in `sleep': (Interrupt)
from (eval):0
from (eval):0:in `loop'
from (eval):0
(eval): [BUG] Segmentation fault
ruby 1.8.7 (2008-08-11 patchlevel 72) [i486-linux]

Abort


But, be aware:
"ruby is not thread-safe. If you embed ruby into a multi-threaded
application then you will need to semaphore protect all access to
ruby. Warning: Insufficient semaphore protection can be hard
debuggable." [1]

[1] http://metaeditor.sourceforge.net/embed/#id2842564
 
I

Ian Leitch

[Note: parts of this message were removed to make it a legal post.]

Thanks,

I did think of using pthreads, though the code I need to eval will regularly
touch any number of existing objects so I don't think there's a way to stay
safe using pthreads. Do you know how to spawn a ruby green thread in C?

2009/7/13 said:
I'm trying to use rb_eval_string to execute a bunch of code and return from
it straight away. My problem is that the code I want to eval contains a
continuous loop. Even if I wrap the code in a thread the call still blocks
due to the loop. Note that I don't get the same behaviour when using eval()
outside of the C API.

E.g:

rb_eval_string("Thread.new { loop { puts 1; sleep 0.2 }}"); <-- blocks
eval("Thread.new { loop { puts 1; sleep 0.2 }}") <--- doesn't block

My guess is to spawn a ruby thread in C and call rb_eval_string inside that,
I can't find any examples of using the thread functions on google though so
I'm a bit stuck. Could someone give me a few pointers or perhaps some
example code?

This is the first time I have ever tried embedding Ruby in C, but I
hope it helps. (The idea is to run ruby from a C thread so the rest
of your C program can maybe run in parallel):


#include <ruby.h>

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

void *do_ruby(void* param)
{
ruby_init();
rb_eval_string("loop { puts 'hello from ruby world'; sleep 5 }");
ruby_finalize();
}

int main(int argc, char *argv[])
{
pthread_t ruby_thread;

printf("BEFORE DO_RUBY\n");

pthread_create( &ruby_thread, NULL, do_ruby, NULL);

printf("AFTER DO_RUBY\n");

pthread_join(ruby_thread, NULL);

return 0;
}

gcc -o foo -lpthread -lruby1.8 -I/usr/lib/ruby/1.8/i486-linux foo.c
./foo
BEFORE DO_RUBY
hello from ruby world
AFTER DO_RUBY
hello from ruby world
hello from ruby world
^C(eval): (eval):0:in `sleep': (Interrupt)
from (eval):0
from (eval):0:in `loop'
from (eval):0
(eval): [BUG] Segmentation fault
ruby 1.8.7 (2008-08-11 patchlevel 72) [i486-linux]

Abort


But, be aware:
"ruby is not thread-safe. If you embed ruby into a multi-threaded
application then you will need to semaphore protect all access to
ruby. Warning: Insufficient semaphore protection can be hard
debuggable." [1]

[1] http://metaeditor.sourceforge.net/embed/#id2842564
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,059
Latest member
cryptoseoagencies

Latest Threads

Top