From f01103ec221c5a261aa96669aa1d32245d78e232 Mon Sep 17 00:00:00 2001 From: Richard Heck Date: Thu, 17 Nov 2011 18:06:06 +0000 Subject: [PATCH] Backport fix for crash reported by Pavel. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/branches/BRANCH_2_0_X@40206 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/Buffer.cpp | 87 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 29 deletions(-) diff --git a/src/Buffer.cpp b/src/Buffer.cpp index 4b86241ab5..d01ff7bce8 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -140,6 +140,10 @@ void showPrintError(string const & name) Alert::error(_("Print document failed"), str); } +/// a list of Buffers we cloned +set cloned_buffer_list; + + } // namespace anon @@ -386,36 +390,50 @@ Buffer::~Buffer() return; } - // loop over children - Impl::BufferPositionMap::iterator it = d->children_positions.begin(); - Impl::BufferPositionMap::iterator end = d->children_positions.end(); - for (; it != end; ++it) { - Buffer * child = const_cast(it->first); - if (d->cloned_buffer_) - delete child; - // The child buffer might have been closed already. - else if (theBufferList().isLoaded(child)) - theBufferList().releaseChild(this, child); - } + if (isClone()) { + // this is in case of recursive includes: we won't try to delete + // ourselves as a child. + cloned_buffer_list.erase(this); + // loop over children + Impl::BufferPositionMap::iterator it = d->children_positions.begin(); + Impl::BufferPositionMap::iterator end = d->children_positions.end(); + for (; it != end; ++it) { + Buffer * child = const_cast(it->first); + if (cloned_buffer_list.erase(child)) + delete child; + } + // FIXME Do we really need to do this right before we delete d? + // clear references to children in macro tables + d->children_positions.clear(); + d->position_to_children.clear(); + } else { + // loop over children + Impl::BufferPositionMap::iterator it = d->children_positions.begin(); + Impl::BufferPositionMap::iterator end = d->children_positions.end(); + for (; it != end; ++it) { + Buffer * child = const_cast(it->first); + if (theBufferList().isLoaded(child)) + theBufferList().releaseChild(this, child); + } - if (!isClean()) { - docstring msg = _("LyX attempted to close a document that had unsaved changes!\n"); - msg += emergencyWrite(); - Alert::warning(_("Attempting to close changed document!"), msg); - } - - // clear references to children in macro tables - d->children_positions.clear(); - d->position_to_children.clear(); + if (!isClean()) { + docstring msg = _("LyX attempted to close a document that had unsaved changes!\n"); + msg += emergencyWrite(); + Alert::warning(_("Attempting to close changed document!"), msg); + } - if (!d->cloned_buffer_ && !d->temppath.destroyDirectory()) { - Alert::warning(_("Could not remove temporary directory"), - bformat(_("Could not remove the temporary directory %1$s"), - from_utf8(d->temppath.absFileName()))); - } + // FIXME Do we really need to do this right before we delete d? + // clear references to children in macro tables + d->children_positions.clear(); + d->position_to_children.clear(); - if (!isClone()) + if (!d->temppath.destroyDirectory()) { + Alert::warning(_("Could not remove temporary directory"), + bformat(_("Could not remove the temporary directory %1$s"), + from_utf8(d->temppath.absFileName()))); + } removePreviews(); + } delete d; } @@ -425,9 +443,20 @@ Buffer * Buffer::clone() const { BufferMap bufmap; masterBuffer()->clone(bufmap); - BufferMap::iterator it = bufmap.find(this); - LASSERT(it != bufmap.end(), return 0); - return it->second; + + // make sure we got cloned + BufferMap::const_iterator bit = bufmap.find(this); + LASSERT(bit != bufmap.end(), return 0); + Buffer * cloned_buffer = bit->second; + + // record the list of cloned buffers + cloned_buffer_list.clear(); + BufferMap::iterator it = bufmap.begin(); + BufferMap::iterator en = bufmap.end(); + for (; it != en; ++it) + cloned_buffer_list.insert(it->second); + + return cloned_buffer; }