From a68a361276d925b58e574e7d0e5a45f0108d82b4 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 14 Jul 2013 15:26:36 +0000 Subject: [PATCH] Fix crash in docview code if view initialization failed. The change of r71371 resulted in using the already destroyed (implicitly, done as part of destroying the wxView that failed to initialize) wxDocument in wxScopeGuard destructor. Avoid this and make the old (i.e. pre-r71371) code exception safe while keeping its semantics exactly, i.e. only delete all views if the document still exists. Also add a comment explaining what's going on here because the ownership rules in docview code are frankly crazy. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74515 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- src/common/docview.cpp | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/common/docview.cpp b/src/common/docview.cpp index fc1c256337..b1d2971fcb 100644 --- a/src/common/docview.cpp +++ b/src/common/docview.cpp @@ -858,19 +858,25 @@ wxDocument *wxDocTemplate::CreateDocument(const wxString& path, long flags) bool wxDocTemplate::InitDocument(wxDocument* doc, const wxString& path, long flags) { - wxScopeGuard g = wxMakeObjGuard(*doc, &wxDocument::DeleteAllViews); + // Normally, if wxDocument::OnCreate() fails, it happens because the view + // initialization fails and then the document is destroyed due to the + // destruction of its last view. But take into account the (currently + // unrealized, AFAICS) possibility of other failures as well and ensure + // that the document is always destroyed if it can't be initialized. + wxTRY + { + doc->SetFilename(path); + doc->SetDocumentTemplate(this); + GetDocumentManager()->AddDocument(doc); + doc->SetCommandProcessor(doc->OnCreateCommandProcessor()); - doc->SetFilename(path); - doc->SetDocumentTemplate(this); - GetDocumentManager()->AddDocument(doc); - doc->SetCommandProcessor(doc->OnCreateCommandProcessor()); - - if ( !doc->OnCreate(path, flags) ) - return false; - - g.Dismiss(); // no need to call DeleteAllViews() anymore - - return true; + return doc->OnCreate(path, flags); + } + wxCATCH_ALL( + if ( GetDocumentManager()->GetDocuments().Member(doc) ) + doc->DeleteAllViews(); + throw; + ) } wxView *wxDocTemplate::CreateView(wxDocument *doc, long flags)