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 | |
| 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.
| -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;  | 
