]> git.saurik.com Git - wxWidgets.git/commitdiff
Fix crash in docview code if view initialization failed.
authorVadim Zeitlin <vadim@wxwidgets.org>
Sun, 14 Jul 2013 15:26:36 +0000 (15:26 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sun, 14 Jul 2013 15:26:36 +0000 (15:26 +0000)
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

index fc1c256337baa61a4766a83b34d5bf24dc56f954..b1d2971fcbf167f89edfbda2d9047306441d8952 100644 (file)
@@ -858,19 +858,25 @@ wxDocument *wxDocTemplate::CreateDocument(const wxString& path, long flags)
 bool
 wxDocTemplate::InitDocument(wxDocument* doc, const wxString& path, long flags)
 {
 bool
 wxDocTemplate::InitDocument(wxDocument* doc, const wxString& path, long flags)
 {
-    wxScopeGuard g = wxMakeObjGuard(*doc, &wxDocument::DeleteAllViews);
-
-    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
+    // 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());
 
 
-    return true;
+        return doc->OnCreate(path, flags);
+    }
+    wxCATCH_ALL(
+        if ( GetDocumentManager()->GetDocuments().Member(doc) )
+            doc->DeleteAllViews();
+        throw;
+    )
 }
 
 wxView *wxDocTemplate::CreateView(wxDocument *doc, long flags)
 }
 
 wxView *wxDocTemplate::CreateView(wxDocument *doc, long flags)