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
|
||||
|
||||
#define RBA_TRY \
|
||||
VALUE __error_msg = Qnil; \
|
||||
int __estatus = 0; \
|
||||
VALUE __exc = Qnil; \
|
||||
VALUE __eclass = Qnil; \
|
||||
{ \
|
||||
try {
|
||||
|
|
@ -636,6 +675,9 @@ private:
|
|||
__estatus = ex.status (); \
|
||||
__eclass = rb_eSystemExit; \
|
||||
__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) { \
|
||||
__eclass = rb_eRuntimeError; \
|
||||
__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 ()); \
|
||||
} \
|
||||
} \
|
||||
if (__eclass == rb_eSystemExit) { \
|
||||
/* HINT: we do the rb_raise outside any destructor code - sometimes this longjmp seems not to work properly */ \
|
||||
if (__exc != Qnil) { \
|
||||
/* 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]; \
|
||||
args [0] = INT2NUM (__estatus); \
|
||||
args [1] = __error_msg; \
|
||||
rb_exc_raise (rb_class_new_instance(2, args, __eclass)); \
|
||||
} 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]; \
|
||||
args [0] = __error_msg; \
|
||||
rb_exc_raise (rb_class_new_instance(1, args, __eclass)); \
|
||||
|
|
@ -1389,41 +1436,6 @@ stderr_winsize (VALUE self)
|
|||
// --------------------------------------------------------------------------
|
||||
// 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;
|
||||
|
||||
struct RubyConstDescriptor
|
||||
|
|
|
|||
|
|
@ -32,26 +32,6 @@
|
|||
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;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -30,12 +30,41 @@
|
|||
#include "gsiMethods.h"
|
||||
#include "gsiSignals.h"
|
||||
#include "tlObject.h"
|
||||
#include "tlScriptError.h"
|
||||
|
||||
#include <ruby.h>
|
||||
|
||||
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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "rba.h"
|
||||
#include "rbaUtils.h"
|
||||
#include "rbaInternal.h"
|
||||
|
||||
#if HAVE_RUBY_VERSION_CODE >= 20200
|
||||
# include <ruby/debug.h>
|
||||
|
|
@ -168,9 +169,9 @@ rba_check_error ()
|
|||
}
|
||||
|
||||
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 {
|
||||
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
|
||||
|
||||
class MyException < RuntimeError
|
||||
def initialize(s)
|
||||
super(s)
|
||||
end
|
||||
end
|
||||
|
||||
class XEdge < RBA::Edge
|
||||
def initialize
|
||||
super(RBA::Point.new(1,2), RBA::Point.new(3,4))
|
||||
|
|
@ -2601,4 +2607,30 @@ class Basic_TestClass < TestBase
|
|||
|
||||
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
|
||||
|
|
|
|||
Loading…
Reference in New Issue