diff options
author | Dan Gudmundsson <[email protected]> | 2014-01-23 15:33:09 +0100 |
---|---|---|
committer | Dan Gudmundsson <[email protected]> | 2014-01-23 15:33:09 +0100 |
commit | fd055cf43486358a413a1fa22f30f0aa711d25e1 (patch) | |
tree | 2439dfc1481c3f3fb9225564e192bf234ccf829a /lib/wx | |
parent | 84a83493c2bd9b01b3d90a2ebef49b0c698c0797 (diff) | |
download | otp-fd055cf43486358a413a1fa22f30f0aa711d25e1.tar.gz otp-fd055cf43486358a413a1fa22f30f0aa711d25e1.tar.bz2 otp-fd055cf43486358a413a1fa22f30f0aa711d25e1.zip |
wx: Delay all deletes if recursed in event loop
Avoids crashes.
Diffstat (limited to 'lib/wx')
-rw-r--r-- | lib/wx/api_gen/wx_gen_cpp.erl | 14 | ||||
-rw-r--r-- | lib/wx/c_src/gen/wxe_funcs.cpp | 13 | ||||
-rw-r--r-- | lib/wx/c_src/wxe_helpers.cpp | 1 | ||||
-rw-r--r-- | lib/wx/c_src/wxe_helpers.h | 13 | ||||
-rw-r--r-- | lib/wx/c_src/wxe_impl.cpp | 41 | ||||
-rw-r--r-- | lib/wx/c_src/wxe_impl.h | 2 |
6 files changed, 57 insertions, 27 deletions
diff --git a/lib/wx/api_gen/wx_gen_cpp.erl b/lib/wx/api_gen/wx_gen_cpp.erl index 6eed0668f6..5ac57e4929 100644 --- a/lib/wx/api_gen/wx_gen_cpp.erl +++ b/lib/wx/api_gen/wx_gen_cpp.erl @@ -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 @@ -190,10 +190,14 @@ gen_funcs(Defs) -> %% w(" case WXE_REMOVE_PORT:~n", []), %% w(" { destroyMemEnv(Ecmd.port); } break;~n", []), w(" case DESTROY_OBJECT: {~n"), - w(" wxObject *This = (wxObject *) getPtr(bp,memenv); "), - w(" if(This) {"), - w(" ((WxeApp *) wxTheApp)->clearPtr((void *) This);~n"), - w(" delete This; }~n } break;~n"), + w(" wxObject *This = (wxObject *) getPtr(bp,memenv);~n"), + w(" if(This) {~n"), + w(" if(recurse_level > 1) {~n"), + w(" delayed_delete->Append(Ecmd.Save());~n"), + w(" } else {~n"), + w(" ((WxeApp *) wxTheApp)->clearPtr((void *) This);~n"), + w(" delete This; }~n"), + w(" } } break;~n"), w(" case WXE_REGISTER_OBJECT: {~n" " registerPid(bp, Ecmd.caller, memenv);~n" " rt.addAtom(\"ok\");~n" 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; |