aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Gudmundsson <[email protected]>2014-01-23 15:33:09 +0100
committerDan Gudmundsson <[email protected]>2014-01-23 15:33:09 +0100
commitfd055cf43486358a413a1fa22f30f0aa711d25e1 (patch)
tree2439dfc1481c3f3fb9225564e192bf234ccf829a
parent84a83493c2bd9b01b3d90a2ebef49b0c698c0797 (diff)
downloadotp-fd055cf43486358a413a1fa22f30f0aa711d25e1.tar.gz
otp-fd055cf43486358a413a1fa22f30f0aa711d25e1.tar.bz2
otp-fd055cf43486358a413a1fa22f30f0aa711d25e1.zip
wx: Delay all deletes if recursed in event loop
Avoids crashes.
-rw-r--r--lib/wx/api_gen/wx_gen_cpp.erl14
-rw-r--r--lib/wx/c_src/gen/wxe_funcs.cpp13
-rw-r--r--lib/wx/c_src/wxe_helpers.cpp1
-rw-r--r--lib/wx/c_src/wxe_helpers.h13
-rw-r--r--lib/wx/c_src/wxe_impl.cpp41
-rw-r--r--lib/wx/c_src/wxe_impl.h2
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;