From fd055cf43486358a413a1fa22f30f0aa711d25e1 Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Thu, 23 Jan 2014 15:33:09 +0100 Subject: wx: Delay all deletes if recursed in event loop Avoids crashes. --- lib/wx/c_src/gen/wxe_funcs.cpp | 13 +++++++++---- lib/wx/c_src/wxe_helpers.cpp | 1 + lib/wx/c_src/wxe_helpers.h | 13 ++++++++++++- lib/wx/c_src/wxe_impl.cpp | 41 +++++++++++++++++++++++++---------------- lib/wx/c_src/wxe_impl.h | 2 +- 5 files changed, 48 insertions(+), 22 deletions(-) (limited to 'lib/wx/c_src') diff --git a/lib/wx/c_src/gen/wxe_funcs.cpp b/lib/wx/c_src/gen/wxe_funcs.cpp index 329af36f4d..82dd414911 100644 --- a/lib/wx/c_src/gen/wxe_funcs.cpp +++ b/lib/wx/c_src/gen/wxe_funcs.cpp @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2008-2013. All Rights Reserved. + * Copyright Ericsson AB 2008-2014. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -45,9 +45,14 @@ void WxeApp::wxe_dispatch(wxeCommand& Ecmd) switch (Ecmd.op) { case DESTROY_OBJECT: { - wxObject *This = (wxObject *) getPtr(bp,memenv); if(This) { ((WxeApp *) wxTheApp)->clearPtr((void *) This); - delete This; } - } break; + wxObject *This = (wxObject *) getPtr(bp,memenv); + if(This) { + if(recurse_level > 1) { + delayed_delete->Append(Ecmd.Save()); + } else { + ((WxeApp *) wxTheApp)->clearPtr((void *) This); + delete This; } + } } break; case WXE_REGISTER_OBJECT: { registerPid(bp, Ecmd.caller, memenv); rt.addAtom("ok"); diff --git a/lib/wx/c_src/wxe_helpers.cpp b/lib/wx/c_src/wxe_helpers.cpp index 9e692e1dc3..15d75080d9 100644 --- a/lib/wx/c_src/wxe_helpers.cpp +++ b/lib/wx/c_src/wxe_helpers.cpp @@ -29,6 +29,7 @@ wxeCommand::wxeCommand(int fc,char * cbuf,int buflen, wxe_data *sd) { WXEBinRef *temp, *start, *prev; int n = 0; + ref_count = 1; caller = driver_caller(sd->port_handle); port = sd->port; op = fc; diff --git a/lib/wx/c_src/wxe_helpers.h b/lib/wx/c_src/wxe_helpers.h index c8a7e35bdb..659bc666c6 100644 --- a/lib/wx/c_src/wxe_helpers.h +++ b/lib/wx/c_src/wxe_helpers.h @@ -43,7 +43,10 @@ class wxeCommand : public wxObject { public: wxeCommand(int fc,char * cbuf,int buflen, wxe_data *); - virtual ~wxeCommand(); + virtual ~wxeCommand(); // Use Delete() + + wxeCommand * Save() {ref_count++; return this; }; + void Delete() {if(--ref_count < 1) delete this;}; ErlDrvTermData caller; ErlDrvTermData port; @@ -51,6 +54,7 @@ class wxeCommand : public wxObject char * buffer; int len; int op; + int ref_count; }; class intListElement { @@ -65,6 +69,13 @@ class intListElement { class intList { public: intList() {list = NULL;}; + ~intList() { + intListElement *head = list; + while(head) { + intListElement *tail=head->cdr; + delete head; + head = tail; + } }; bool IsEmpty() {return list == NULL;}; void Append(int Element) { list = new intListElement(Element, list); }; int Pop() { diff --git a/lib/wx/c_src/wxe_impl.cpp b/lib/wx/c_src/wxe_impl.cpp index 1e8dfc0e58..5964ccfd00 100644 --- a/lib/wx/c_src/wxe_impl.cpp +++ b/lib/wx/c_src/wxe_impl.cpp @@ -126,6 +126,7 @@ bool WxeApp::OnInit() cb_buff = NULL; recurse_level = 0; delayed_cleanup = new wxList; + delayed_delete = new wxList; wxe_ps_init2(); // wxIdleEvent::SetMode(wxIDLE_PROCESS_SPECIFIED); // Hmm printpreview doesn't work in 2.9 with this @@ -213,16 +214,26 @@ void WxeApp::dispatch_cmds() recurse_level--; wxe_batch_caller = 0; erl_drv_mutex_unlock(wxe_batch_locker_m); - // Cleanup old memenv's - if(recurse_level == 0 && delayed_cleanup->size() > 0) { - for( wxList::compatibility_iterator node = delayed_cleanup->GetFirst(); - node; - node = delayed_cleanup->GetFirst()) { - wxeMetaCommand *event = (wxeMetaCommand *)node->GetData(); - delayed_cleanup->Erase(node); - destroyMemEnv(*event); - delete event; - } + // Cleanup old memenv's and deleted objects + if(recurse_level == 0) { + if(delayed_delete->size() > 0) + for( wxList::compatibility_iterator node = delayed_delete->GetFirst(); + node; + node = delayed_delete->GetFirst()) { + wxeCommand *event = (wxeCommand *)node->GetData(); + delayed_delete->Erase(node); + wxe_dispatch(*event); + event->Delete(); + } + if(delayed_cleanup->size() > 0) + for( wxList::compatibility_iterator node = delayed_cleanup->GetFirst(); + node; + node = delayed_cleanup->GetFirst()) { + wxeMetaCommand *event = (wxeMetaCommand *)node->GetData(); + delayed_cleanup->Erase(node); + destroyMemEnv(*event); + delete event; + } } } @@ -275,7 +286,7 @@ int WxeApp::dispatch(wxList * batch, int blevel, int list_type) erl_drv_mutex_lock(wxe_batch_locker_m); break; } - delete event; + event->Delete(); } } else { if((list_type == WXE_STORED) || (blevel <= 0 && list_type == WXE_NORMAL)) { @@ -356,7 +367,7 @@ void WxeApp::dispatch_cb(wxList * batch, wxList * temp, ErlDrvTermData process) return; break; } - delete event; + event->Delete(); } else { // fprintf(stderr, " save %d \r\n", event->op); temp->Append(event); @@ -397,7 +408,6 @@ void WxeApp::destroyMemEnv(wxeMetaCommand& Ecmd) { // Clear incoming cmd queue first // dispatch_cmds(); - int delay = false; wxWindow *parent = NULL; wxeMemEnv * memenv = refmap[Ecmd.port]; @@ -430,7 +440,6 @@ void WxeApp::destroyMemEnv(wxeMetaCommand& Ecmd) if(recurse_level > 0) { // Delay delete until we are out of dispatch* delayed_cleanup->Append(Ecmd.Clone()); - delay = true; } else { delete win; } @@ -439,8 +448,8 @@ void WxeApp::destroyMemEnv(wxeMetaCommand& Ecmd) } } - if(delay) - return; + if(recurse_level > 0) + return; // First pass, delete all top parents/windows of all linked objects // fprintf(stderr, "close port %x\r\n", Ecmd.port);fflush(stderr); diff --git a/lib/wx/c_src/wxe_impl.h b/lib/wx/c_src/wxe_impl.h index 6beb0eb9b9..bb54961edd 100644 --- a/lib/wx/c_src/wxe_impl.h +++ b/lib/wx/c_src/wxe_impl.h @@ -81,7 +81,7 @@ public: int recurse_level; wxList * delayed_cleanup; - + wxList * delayed_delete; // Temp container for callbacks char *cb_buff; int cb_len; -- cgit v1.2.3