Skip to content

Commit

Permalink
fix potential problems with cloning async method call events and impr…
Browse files Browse the repository at this point in the history
…ove reporting unexpected situations
  • Loading branch information
mcorino committed Nov 15, 2024
1 parent 4d85bda commit 72979fb
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 7 deletions.
11 changes: 11 additions & 0 deletions rakelib/lib/director/event.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,17 @@ def setup
static VALUE Evt_Type_Map = NULL;
static VALUE wxRuby_WrapClonedWxEvent(wxEvent* wx_evt)
{
if (wx_evt->GetEventType() == wxEVT_ASYNC_METHOD_CALL)
{
// async method call events use the custom RbAsyncProcCallEvent class (see event_handler)
// which has no mapped Ruby class and also has no distinct dynamic wx class
// it should never be accessible nor cloned in Ruby space;
// let's report it and simply delete the event and return nil here if this somehow happens
std::wcerr << std::endl << "WARNING: invalid clone operation executed on AsyncMethodCallEvent" << std::endl;
delete wx_evt;
return Qnil;
}
wxString class_name( wx_evt->GetClassInfo()->GetClassName() );
if (class_name == "wxEvent" || class_name == "wxCommandEvent")
{
Expand Down
27 changes: 20 additions & 7 deletions rakelib/lib/director/event_handler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,10 @@ class RbAsyncProcCallEvent : public wxAsyncMethodCallEvent
virtual wxEvent *Clone() const wxOVERRIDE
{
return new RbAsyncProcCallEvent(*this);
RbAsyncProcCallEvent* evt_clone = new RbAsyncProcCallEvent(*this);
// make sure to track the clone and the call object too
wxRuby_AddTracking( (void*)evt_clone, evt_clone->m_rb_call);
return evt_clone;
}
virtual void Execute() wxOVERRIDE
Expand All @@ -257,12 +260,22 @@ class RbAsyncProcCallEvent : public wxAsyncMethodCallEvent
if (TYPE(m_rb_call) == T_ARRAY)
{
VALUE proc = rb_ary_entry(m_rb_call, 0);
VALUE args = rb_ary_subseq(m_rb_call, 1, RARRAY_LEN(m_rb_call)-1);
rc = wxRuby_Funcall(ex_caught, proc, call_id(), args);
if (RARRAY_LEN(m_rb_call) > 1)
{
VALUE args = rb_ary_subseq(m_rb_call, 1, RARRAY_LEN(m_rb_call)-1);
rc = wxRuby_Funcall(ex_caught, proc, call_id(), args);
}
else
{
rc = wxRuby_Funcall(ex_caught, proc, call_id(), (int)0);
}
}
else
{
rc = wxRuby_Funcall(ex_caught, m_rb_call, call_id(), (int)0);
// should never happen
VALUE msg = rb_str_new2("UNEXPECTED ERROR: Asynchronous Proc Event has invalid call spec!");
wxRuby_PrintException(rb_class_new_instance(1, &msg, rb_eRuntimeError));
exit(1);
}
if (ex_caught)
{
Expand Down Expand Up @@ -333,9 +346,9 @@ class RbAsyncProcCallEvent : public wxAsyncMethodCallEvent
void call_after(VALUE call)
{
// valid call object?
VALUE proc;
if (TYPE(call) == T_ARRAY &&
(rb_obj_is_kind_of(proc = rb_ary_entry(call, 0), rb_cProc)
VALUE proc = TYPE(call) == T_ARRAY ? rb_ary_entry(call, 0) : Qnil;
if (!NIL_P(proc) &&
(rb_obj_is_kind_of(proc, rb_cProc)
||
rb_obj_is_kind_of(proc, rb_cMethod)))
{
Expand Down

0 comments on commit 72979fb

Please sign in to comment.