Threading in Plasma applets

Richard Dale richard.j.dale at gmail.com
Mon Apr 7 12:23:17 CEST 2008


2008/2/19 Sebastian Sauer <mail at dipe.org>:

> On Tuesday 19 February 2008, Aaron J. Seigo wrote:
> > On Tuesday 19 February 2008, Richard Dale wrote:
> > > were having problems too, which makes me think it might be some sort
> > > of Ruby problem, rather than a QtRuby specific problem. Is that
> > > possible?
> >
> > could be.. and yes, the kross based ScripEngines were dieing badly in
> > threading related deaths while the same engines when running python
> scripts
> > work fine.
>
> well, threading should work. The reason why it was failing, is that there
> is
> still a bit of testingcode within krossruby that doesn't seem to be
> thread-safe (yet). Someone is able to work around this by removing the
> #define KROSS_RUBY_EXPLICIT_GC
> in kdebindings/ruby/krossruby/rubyconfig.h (should also increase the speed
> a
> lot, that code does run the garbage collector at each possible step to
> discover problems faster, but seems the gc is not very thread-friendly ;)
>
> @richard; normaly it should be enough to;
> const int critical = rb_thread_critical;
> rb_thread_critical = Qtrue;
> e.g. rb_funcall() ... (and while on that code, it may also an idea to wrap
> rb_funcall's into rb_rescue2's to catch exceptions and prevent
> rb_bug's/crashes and, not sure if that's really needed, to ruby_in_eval++
> and
> ruby_in_eval-- to prevent infinite loop's)
> rb_thread_critical = critical;
>
> Anyway. I still try to get the
> playground/base/plasma/scriptengines/kross/examples/example_ruby_runner
> working, but seems it still fails somehow. So, I am not able to test it
> aka
> look if there are probably more bugs related to threading :-/
>
> Attached is the patch I applied. I guess atm the problem is, that the
> match+exec methods in kdebase/libs/plasma/scripting/runnerscript.h arn't
> virtual any longer. So, somehow I miss how it needs to be changed to work
> again :-/

The patch didn't actually have the rb_thread_critical change, but I got
enough from your description above to try it out. I also added rb_protect()
to the virtual method callbacks and slot invocations in qtruby. If there was
an error I used rb_backtrace() to print where the ruby runtime failed.

I couldn't see that rb_thread_critical made any difference for me, however
I  have found what the problem is for qtruby/plasma - it keeps running out
of stack and throwing sysstack_error exceptions. It might be that
rb_thread_critical makes ruby only run in one thread which would minimise
stack use perhaps.

I added some diagnostics to my version of ruby in gc.c:

#define CHECK_STACK(ret) do {\
    SET_STACK_END;\
    (ret) = (STACK_LENGTH > STACK_LEVEL_MAX + GC_WATER_MARK);\
    printf("CHECK_STACK ret: %d STACK_LENGTH: %d > STACK_LEVEL_MAX: %u +
GC_WATER_MARK: %d\n", \
            ret, STACK_LENGTH, STACK_LEVEL_MAX, GC_WATER_MARK); \
} while (0)

So that it prints out the numbers everytime it does a stack check. The
output from Plasma when running the Ruby clock looks like this:

..
CHECK_STACK ret: 0 STACK_LENGTH: 4120 > STACK_LEVEL_MAX: 15987856d +
GC_WATER_MARK: 512
1117CHECK_STACK ret: 0 STACK_LENGTH: 2384 > STACK_LEVEL_MAX: 15987856 +
GC_WATER_MARK: 512
0CHECK_STACK ret: 1 STACK_LENGTH: -236 > STACK_LEVEL_MAX: 15987856 +
GC_WATER_MARK: 512
stack_check() raising a sysstack_error
        from clock.rb

Most of the time the stack length is 2500-4000 (not sure what the units
are), but every now and then it goes negative and Ruby throws an exception.
I tried the ruby cannon game tutorial t14 and its STACK_LENGTH numbers were
about 1500 higher and they never went negative.

ruby t14.rb |
> grep STACK_LENGTH |
>  awk 'BEGIN { min = 99999 }  \
> { total_stack_length += $5 ; if ($5 < min)  min = $5 } \
> END { print total_stack_length / NR ; print min }'
4239.56
1400

mardigras rdale 586% cat plasma.log |
> grep STACK_LENGTH |
>  awk 'BEGIN { min = 99999 }  \
> { total_stack_length += $5 ; if ($5 < min)  min = $5 } \
> END { print total_stack_length / NR ; print min }'
2494.53
-236

I tried a setrlimit to change the stack size in the initialization of the
ruby plugin:

struct rlimit rlim;
rlim.rlim_cur = 65000000;
int status = setrlimit(RLIMIT_STACK, &rlim);

Although it made the STACK_LEVEL_MAX figure bigger (15987856 in the above
example), it didn't make any difference. I wonder if Ruby is getting the
stack direction wrong, I've no idea - so I'll do a bit of googling and
investigate further.

-- Richard
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.kde.org/pipermail/panel-devel/attachments/20080407/ebd675d4/attachment.html 


More information about the Panel-devel mailing list