On 12/29/2016 01:21 AM, Guillaume Munch wrote: > Le 27/12/2016 à 23:11, Scott Kostyshak a écrit : >> On Tue, May 31, 2016 at 01:15:38AM +0200, Guillaume Munch wrote: >>> commit 1cc14a31ca8320d881b674f93c34a09cf1666cca >>> Author: Guillaume Munch <g...@lyx.org> >>> Date: Mon May 30 21:42:08 2016 +0100 >>> >>> TocWidget: fix an erroneous collapse and optimise updates based >>> on profiling >>> >>> TocModels::reset() in GuiView::structureChanged() collapses the >>> TocWidget, and >>> therefore requires an update right after, which was missing. >>> >>> In fact, profiling TocWidget::updateView() shows that delaying >>> the update is >>> good only for fast keypresses (essentially movement). It costs >>> 5% of a >>> char-forward operation in a document with approx. 100 table of >>> contents >>> items. The update optimisation has been rewritten to take this >>> data into >>> account. >> >> A git bisect suggests this causes a SIGSEGV. To reproduce: >> >> 1. open the attached file >> 2. open the outline pane >> 3. put the cursor just to the left of "Hello" (but inside the caption >> inset) >> 4. "Save As" to a new filename. >> >> Can you reproduce? >> >> Backtrace is attached. >> > > Hi, > > The root of the issue is in Buffer::reload() called during "Save As". > After loadLyXFile() there, all the insets have been deleted, and > therefore the Inset pointer > GuiView::documentBufferView()->cursor().inset() is dangling. Immediately > after loadLyXFile(), reload() calls updateBuffer() from your backtrace > which then crashes.
Here's a modified version of this patch, taking into account JMarc's suggestions. Richard
>From 0eec72ed8b1c8cd5cb7abc1a618990e2f3c87343 Mon Sep 17 00:00:00 2001 From: Richard Heck <rgh...@lyx.org> Date: Fri, 30 Dec 2016 11:24:44 -0500 Subject: [PATCH] Fix cursor after reloading Buffer. Fixes a crash discovered by Scott. Modification of a patch due to Guillaume. --- src/Buffer.cpp | 8 ++++++++ src/Buffer.h | 2 ++ src/frontends/Delegates.h | 2 ++ src/frontends/qt4/GuiView.cpp | 7 +++++++ src/frontends/qt4/GuiView.h | 8 ++++---- 5 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/Buffer.cpp b/src/Buffer.cpp index 3652e7a..d15db79 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -3816,6 +3816,13 @@ ErrorList & Buffer::errorList(string const & type) const } +void Buffer::updateCursors() const +{ + if (d->gui_) + d->gui_->updateCursors(); +} + + void Buffer::updateTocItem(std::string const & type, DocIterator const & dit) const { @@ -5014,6 +5021,7 @@ Buffer::ReadStatus Buffer::reload() d->setParent(0); ReadStatus const status = loadLyXFile(); if (status == ReadSuccess) { + updateCursors(); updateBuffer(); changed(true); updateTitles(); diff --git a/src/Buffer.h b/src/Buffer.h index 0cb7026..ba68a45 100644 --- a/src/Buffer.h +++ b/src/Buffer.h @@ -682,6 +682,8 @@ public: bool lastPreviewError() const; private: + /// This function is called when inset pointers have changed. + void updateCursors() const; /// ExportStatus doExport(std::string const & target, bool put_in_tempdir, std::string & result_file) const; diff --git a/src/frontends/Delegates.h b/src/frontends/Delegates.h index d13af7e..0f969e6 100644 --- a/src/frontends/Delegates.h +++ b/src/frontends/Delegates.h @@ -72,6 +72,8 @@ public: virtual void setBusy(bool) = 0; /// Reset autosave timers for all users. virtual void resetAutosaveTimers() = 0; + /// This function is called when inset pointers have changed. + virtual void updateCursors() = 0; }; } // namespace frontend diff --git a/src/frontends/qt4/GuiView.cpp b/src/frontends/qt4/GuiView.cpp index 90b43eb..b3768b0 100644 --- a/src/frontends/qt4/GuiView.cpp +++ b/src/frontends/qt4/GuiView.cpp @@ -1661,6 +1661,13 @@ void GuiView::structureChanged() } +void GuiView::updateCursors() +{ + if (documentBufferView()) + documentBufferView()->cursor().fixIfBroken(); +} + + void GuiView::updateDialog(string const & name, string const & data) { if (!isDialogVisible(name)) diff --git a/src/frontends/qt4/GuiView.h b/src/frontends/qt4/GuiView.h index a864f4b..58c0202 100644 --- a/src/frontends/qt4/GuiView.h +++ b/src/frontends/qt4/GuiView.h @@ -107,10 +107,6 @@ public: void newDocument(std::string const & filename, bool fromTemplate); - /// display a message in the view - /// could be called from any thread - void message(docstring const &); - bool getStatus(FuncRequest const & cmd, FuncStatus & flag); /// dispatch command. /// \return true if the \c FuncRequest has been dispatched. @@ -167,6 +163,10 @@ public: void errors(std::string const &, bool from_master = false); void structureChanged(); void updateTocItem(std::string const &, DocIterator const &); + void updateCursors(); + /// display a message in the view + /// could be called from any thread + void message(docstring const &); //@} /// -- 2.7.4