Threading in Plasma applets

Richard Dale richard.j.dale at gmail.com
Mon Apr 7 13:38:09 CEST 2008


On Mon, Apr 7, 2008 at 11:23 AM, Richard Dale <richard.j.dale at gmail.com>
wrote:


> 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.
>
Doh! The problem isn't that Ruby is going off the end of the stack, it's
that it is dropping below where it believes the stack started. So if I make
the stack huge it doesn't have any effect on this underflow. When a ruby
plasma plugin is loaded the RUBY_INIT_STACK macro will assume that the stack
starts where it happens to be for the plugin loader code. It really needs to
be run in main() though as that is where the real root of the stack. One way
to work round this is to call RUBY_INIT_STACK at every entry point to the
Ruby code (eg virtual method callbacks, and slot invocations). But make sure
it is only called once if a virtual method calls another virtual method for
instance by incrementing and decrementing a global 'nested_calls' count.
Swig uses a couple of macros to do that:

/*
  If your swig extension is to be run within an embedded ruby and has
  director callbacks, you should set -DRUBY_EMBEDDED during compilation.
  This will reset ruby's stack frame on each entry point from the main
  program the first time a virtual director function is invoked (in a
  non-recursive way).
  If this is not done, you run the risk of Ruby trashing the stack.
*/

#ifdef RUBY_EMBEDDED

#  define SWIG_INIT_STACK                            \
      if ( !swig_virtual_calls ) { RUBY_INIT_STACK } \
      ++swig_virtual_calls;
#  define SWIG_RELEASE_STACK --swig_virtual_calls;
#  define Ruby_DirectorTypeMismatchException(x) \
          rb_raise( rb_eTypeError, x ); return c_result;

      static unsigned int swig_virtual_calls = 0;

#else  /* normal non-embedded extension */

#  define SWIG_INIT_STACK
#  define SWIG_RELEASE_STACK
#  define Ruby_DirectorTypeMismatchException(x) \
          throw Swig::DirectorTypeMismatchException( x );

#endif  /* RUBY_EMBEDDED *

 Another way might be to provide a longjmp target in the Plasma main()
function that the Ruby extension code could jump to and then call
RUBY_INIT_STACK there.

Another way would be to always assume that Plasma will load Ruby code, and
introduce a link time dependency and just call RUBY_INIT_STACK/ruby_init()
in the main(), but I don't think that is very elegant.

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


More information about the Panel-devel mailing list