mirror of https://github.com/KLayout/klayout.git
Fixed #26 (Exceptions are reported every time they propagate up in the call chain in the ruby debugger)
This commit is contained in:
parent
1bb662b9ed
commit
fdb012aa2d
|
|
@ -618,12 +618,51 @@ private:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Ruby interpreter private data
|
||||||
|
|
||||||
|
struct RubyInterpreterPrivateData
|
||||||
|
{
|
||||||
|
RubyInterpreterPrivateData ()
|
||||||
|
{
|
||||||
|
saved_stderr = Qnil;
|
||||||
|
saved_stdout = Qnil;
|
||||||
|
stdout_klass = Qnil;
|
||||||
|
stderr_klass = Qnil;
|
||||||
|
current_console = 0;
|
||||||
|
current_exec_handler = 0;
|
||||||
|
current_exec_level = 0;
|
||||||
|
in_trace = false;
|
||||||
|
exit_on_next = false;
|
||||||
|
block_exceptions = false;
|
||||||
|
ignore_next_exception = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
VALUE saved_stderr;
|
||||||
|
VALUE saved_stdout;
|
||||||
|
VALUE stdout_klass;
|
||||||
|
VALUE stderr_klass;
|
||||||
|
gsi::Console *current_console;
|
||||||
|
std::vector<gsi::Console *> consoles;
|
||||||
|
gsi::ExecutionHandler *current_exec_handler;
|
||||||
|
int current_exec_level;
|
||||||
|
bool in_trace;
|
||||||
|
bool exit_on_next;
|
||||||
|
bool block_exceptions;
|
||||||
|
bool ignore_next_exception;
|
||||||
|
std::string debugger_scope;
|
||||||
|
std::map<const char *, size_t> file_id_map;
|
||||||
|
std::vector<gsi::ExecutionHandler *> exec_handlers;
|
||||||
|
std::set<std::string> package_paths;
|
||||||
|
};
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// Ruby API
|
// Ruby API
|
||||||
|
|
||||||
#define RBA_TRY \
|
#define RBA_TRY \
|
||||||
VALUE __error_msg = Qnil; \
|
VALUE __error_msg = Qnil; \
|
||||||
int __estatus = 0; \
|
int __estatus = 0; \
|
||||||
|
VALUE __exc = Qnil; \
|
||||||
VALUE __eclass = Qnil; \
|
VALUE __eclass = Qnil; \
|
||||||
{ \
|
{ \
|
||||||
try {
|
try {
|
||||||
|
|
@ -636,6 +675,9 @@ private:
|
||||||
__estatus = ex.status (); \
|
__estatus = ex.status (); \
|
||||||
__eclass = rb_eSystemExit; \
|
__eclass = rb_eSystemExit; \
|
||||||
__error_msg = rb_str_new2 ((ex.msg () + tl::to_string (QObject::tr (" in ")) + (where)).c_str ()); \
|
__error_msg = rb_str_new2 ((ex.msg () + tl::to_string (QObject::tr (" in ")) + (where)).c_str ()); \
|
||||||
|
} catch (rba::RubyError &ex) { \
|
||||||
|
__eclass = rb_eRuntimeError; \
|
||||||
|
__exc = ex.exc (); \
|
||||||
} catch (tl::Exception &ex) { \
|
} catch (tl::Exception &ex) { \
|
||||||
__eclass = rb_eRuntimeError; \
|
__eclass = rb_eRuntimeError; \
|
||||||
__error_msg = rb_str_new2 ((ex.msg () + tl::to_string (QObject::tr (" in ")) + (where)).c_str ()); \
|
__error_msg = rb_str_new2 ((ex.msg () + tl::to_string (QObject::tr (" in ")) + (where)).c_str ()); \
|
||||||
|
|
@ -644,14 +686,19 @@ private:
|
||||||
__error_msg = rb_str_new2 ((tl::to_string (QObject::tr ("Unspecific exception in ")) + (where)).c_str ()); \
|
__error_msg = rb_str_new2 ((tl::to_string (QObject::tr ("Unspecific exception in ")) + (where)).c_str ()); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
if (__eclass == rb_eSystemExit) { \
|
if (__exc != Qnil) { \
|
||||||
/* HINT: we do the rb_raise outside any destructor code - sometimes this longjmp seems not to work properly */ \
|
/* Reraise the exception without blocking in the debugger */ \
|
||||||
|
/* TODO: should not access private data */ \
|
||||||
|
RubyInterpreter::instance ()->d->block_exceptions = true; \
|
||||||
|
rb_exc_raise (__exc); \
|
||||||
|
} else if (__eclass == rb_eSystemExit) { \
|
||||||
|
/* HINT: we do the rb_raise outside any destructor code - sometimes this longjmp seems not to work properly */ \
|
||||||
VALUE args [2]; \
|
VALUE args [2]; \
|
||||||
args [0] = INT2NUM (__estatus); \
|
args [0] = INT2NUM (__estatus); \
|
||||||
args [1] = __error_msg; \
|
args [1] = __error_msg; \
|
||||||
rb_exc_raise (rb_class_new_instance(2, args, __eclass)); \
|
rb_exc_raise (rb_class_new_instance(2, args, __eclass)); \
|
||||||
} else if (__eclass != Qnil) { \
|
} else if (__eclass != Qnil) { \
|
||||||
/* HINT: we do the rb_raise outside any destructor code - sometimes this longjmp seems not to work properly */ \
|
/* HINT: we do the rb_raise outside any destructor code - sometimes this longjmp seems not to work properly */ \
|
||||||
VALUE args [1]; \
|
VALUE args [1]; \
|
||||||
args [0] = __error_msg; \
|
args [0] = __error_msg; \
|
||||||
rb_exc_raise (rb_class_new_instance(1, args, __eclass)); \
|
rb_exc_raise (rb_class_new_instance(1, args, __eclass)); \
|
||||||
|
|
@ -1389,41 +1436,6 @@ stderr_winsize (VALUE self)
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// RubyInterpreter implementation
|
// RubyInterpreter implementation
|
||||||
|
|
||||||
struct RubyInterpreterPrivateData
|
|
||||||
{
|
|
||||||
RubyInterpreterPrivateData ()
|
|
||||||
{
|
|
||||||
saved_stderr = Qnil;
|
|
||||||
saved_stdout = Qnil;
|
|
||||||
stdout_klass = Qnil;
|
|
||||||
stderr_klass = Qnil;
|
|
||||||
current_console = 0;
|
|
||||||
current_exec_handler = 0;
|
|
||||||
current_exec_level = 0;
|
|
||||||
in_trace = false;
|
|
||||||
exit_on_next = false;
|
|
||||||
block_exceptions = false;
|
|
||||||
ignore_next_exception = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
VALUE saved_stderr;
|
|
||||||
VALUE saved_stdout;
|
|
||||||
VALUE stdout_klass;
|
|
||||||
VALUE stderr_klass;
|
|
||||||
gsi::Console *current_console;
|
|
||||||
std::vector<gsi::Console *> consoles;
|
|
||||||
gsi::ExecutionHandler *current_exec_handler;
|
|
||||||
int current_exec_level;
|
|
||||||
bool in_trace;
|
|
||||||
bool exit_on_next;
|
|
||||||
bool block_exceptions;
|
|
||||||
bool ignore_next_exception;
|
|
||||||
std::string debugger_scope;
|
|
||||||
std::map<const char *, size_t> file_id_map;
|
|
||||||
std::vector<gsi::ExecutionHandler *> exec_handlers;
|
|
||||||
std::set<std::string> package_paths;
|
|
||||||
};
|
|
||||||
|
|
||||||
static RubyInterpreter *sp_rba_interpreter = 0;
|
static RubyInterpreter *sp_rba_interpreter = 0;
|
||||||
|
|
||||||
struct RubyConstDescriptor
|
struct RubyConstDescriptor
|
||||||
|
|
|
||||||
|
|
@ -32,26 +32,6 @@
|
||||||
namespace rba
|
namespace rba
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief A class encapsulating a ruby exception
|
|
||||||
*/
|
|
||||||
class RBA_PUBLIC RubyError
|
|
||||||
: public tl::ScriptError
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
RubyError (const char *msg, const char *cls, const std::vector <tl::BacktraceElement> &backtrace)
|
|
||||||
: tl::ScriptError (msg, cls, backtrace)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
RubyError (const char *msg, const char *sourcefile, int line, const char *cls, const std::vector <tl::BacktraceElement> &backtrace)
|
|
||||||
: tl::ScriptError (msg, sourcefile, line, cls, backtrace)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
RubyError (const RubyError &d)
|
|
||||||
: tl::ScriptError (d)
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RubyInterpreterPrivateData;
|
struct RubyInterpreterPrivateData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -30,12 +30,41 @@
|
||||||
#include "gsiMethods.h"
|
#include "gsiMethods.h"
|
||||||
#include "gsiSignals.h"
|
#include "gsiSignals.h"
|
||||||
#include "tlObject.h"
|
#include "tlObject.h"
|
||||||
|
#include "tlScriptError.h"
|
||||||
|
|
||||||
#include <ruby.h>
|
#include <ruby.h>
|
||||||
|
|
||||||
namespace rba
|
namespace rba
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A class encapsulating a ruby exception
|
||||||
|
*/
|
||||||
|
class RubyError
|
||||||
|
: public tl::ScriptError
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RubyError (VALUE exc, const char *msg, const char *cls, const std::vector <tl::BacktraceElement> &backtrace)
|
||||||
|
: tl::ScriptError (msg, cls, backtrace), m_exc (exc)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
RubyError (VALUE exc, const char *msg, const char *sourcefile, int line, const char *cls, const std::vector <tl::BacktraceElement> &backtrace)
|
||||||
|
: tl::ScriptError (msg, sourcefile, line, cls, backtrace), m_exc (exc)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
RubyError (const RubyError &d)
|
||||||
|
: tl::ScriptError (d), m_exc (d.m_exc)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
VALUE exc () const
|
||||||
|
{
|
||||||
|
return m_exc;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
VALUE m_exc;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The proxy object that represents the C++ object on the Ruby side
|
* @brief The proxy object that represents the C++ object on the Ruby side
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include "rba.h"
|
#include "rba.h"
|
||||||
#include "rbaUtils.h"
|
#include "rbaUtils.h"
|
||||||
|
#include "rbaInternal.h"
|
||||||
|
|
||||||
#if HAVE_RUBY_VERSION_CODE >= 20200
|
#if HAVE_RUBY_VERSION_CODE >= 20200
|
||||||
# include <ruby/debug.h>
|
# include <ruby/debug.h>
|
||||||
|
|
@ -168,9 +169,9 @@ rba_check_error ()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.line > 0) {
|
if (info.line > 0) {
|
||||||
throw RubyError (emsg.c_str (), info.file.c_str (), info.line, eclass.c_str (), bt);
|
throw RubyError (lasterr, emsg.c_str (), info.file.c_str (), info.line, eclass.c_str (), bt);
|
||||||
} else {
|
} else {
|
||||||
throw RubyError (emsg.c_str (), eclass.c_str (), bt);
|
throw RubyError (lasterr, emsg.c_str (), eclass.c_str (), bt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,12 @@ private
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class MyException < RuntimeError
|
||||||
|
def initialize(s)
|
||||||
|
super(s)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
class XEdge < RBA::Edge
|
class XEdge < RBA::Edge
|
||||||
def initialize
|
def initialize
|
||||||
super(RBA::Point.new(1,2), RBA::Point.new(3,4))
|
super(RBA::Point.new(1,2), RBA::Point.new(3,4))
|
||||||
|
|
@ -2601,4 +2607,30 @@ class Basic_TestClass < TestBase
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_73
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
poly = RBA::Polygon::new(RBA::Box::new(0, 0, 100, 100))
|
||||||
|
|
||||||
|
# passing exceptions over iterators is critical because it involves
|
||||||
|
# a Ruby/C++ and C++/Ruby transition
|
||||||
|
poly.each_edge do |e|
|
||||||
|
raise MyException::new("some exception")
|
||||||
|
end
|
||||||
|
|
||||||
|
rescue => ex
|
||||||
|
assert_equal(ex.class.to_s, "MyException")
|
||||||
|
assert_equal(ex.to_s, "some exception")
|
||||||
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
|
raise MyException::new("another exception")
|
||||||
|
rescue => ex
|
||||||
|
assert_equal(ex.class.to_s, "MyException")
|
||||||
|
assert_equal(ex.to_s, "another exception")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue