]> git.lyx.org Git - features.git/commitdiff
Add patcheset for building with gcc 4.6.
authorPavel Sanda <sanda@lyx.org>
Fri, 17 Nov 2017 12:58:49 +0000 (13:58 +0100)
committerPavel Sanda <sanda@lyx.org>
Fri, 17 Nov 2017 12:58:49 +0000 (13:58 +0100)
Reverts couple patches (external file monitor stuff) committed
while ago by GM. One can expect some bugs wrt external
file monitoring; don't use this patch blindly.

development/gcc_4.6.patchset [new file with mode: 0644]

diff --git a/development/gcc_4.6.patchset b/development/gcc_4.6.patchset
new file mode 100644 (file)
index 0000000..946f179
--- /dev/null
@@ -0,0 +1,1768 @@
+commit 465cd79bcbab3e036cf86ab4682386c255a91eb6
+Author: Pavel Sanda <psanda@ucsd.edu>
+Date:   Thu Nov 16 09:33:29 2017 -0800
+
+    move initialization so older gcc still works
+
+diff --git a/src/frontends/qt4/GuiView.cpp b/src/frontends/qt4/GuiView.cpp
+index 68ef3b9..b76138b 100644
+--- a/src/frontends/qt4/GuiView.cpp
++++ b/src/frontends/qt4/GuiView.cpp
+@@ -508,7 +508,7 @@ QSet<Buffer const *> GuiView::GuiViewPrivate::busyBuffers;
+ GuiView::GuiView(int id)
+       : d(*new GuiViewPrivate(this)), id_(id), closing_(false), busy_(0),
+-        command_execute_(false), minibuffer_focus_(false), devel_mode_(false)
++        command_execute_(false), minibuffer_focus_(false), zoom_ratio_(1.0), devel_mode_(false)
+ {
+       connect(this, SIGNAL(bufferViewChanged()),
+               this, SLOT(onBufferViewChanged()));
+diff --git a/src/frontends/qt4/GuiView.h b/src/frontends/qt4/GuiView.h
+index ecf4e44..ed80ca3 100644
+--- a/src/frontends/qt4/GuiView.h
++++ b/src/frontends/qt4/GuiView.h
+@@ -472,7 +472,7 @@ private:
+       /// The rate from which the actual zoom value is calculated
+       /// from the default zoom pref
+-      double zoom_ratio_ = 1.0;
++      double zoom_ratio_;
+       /// Minimum zoom percentage
+       static int const zoom_min_ = 10;
+
+commit de8c60ba2a3779b31a1d8526541a9583b076221c
+Author: Pavel Sanda <psanda@ucsd.edu>
+Date:   Thu Nov 16 09:15:07 2017 -0800
+
+    Revert b30161b59 (Remove FileMonitorBlocker which does not work reliably on all platforms)
+
+diff --git a/src/Buffer.cpp b/src/Buffer.cpp
+index 9ec20e0..6e37ee9 100644
+--- a/src/Buffer.cpp
++++ b/src/Buffer.cpp
+@@ -383,6 +383,9 @@ public:
+       /// Notify or clear of external modification
+       void fileExternallyModified(bool exists);
++      /// Block notifications of external modifications
++      FileMonitorBlocker blockFileMonitor() { return file_monitor_->block(); }
++
+       /// has been externally modified? Can be reset by the user.
+       mutable bool externally_modified_;
+@@ -1379,6 +1382,7 @@ FileName Buffer::getBackupName() const {
+ // Should probably be moved to somewhere else: BufferView? GuiView?
+ bool Buffer::save() const
+ {
++      FileMonitorBlocker block = d->blockFileMonitor();
+       docstring const file = makeDisplayPath(absFileName(), 20);
+       d->filename.refresh();
+@@ -5344,7 +5348,8 @@ void Buffer::Impl::refreshFileMonitor()
+ void Buffer::Impl::fileExternallyModified(bool const exists)
+ {
+-      // ignore notifications after our own saving operations
++      // prevent false positives, because FileMonitorBlocker is not enough on
++      // OSX.
+       if (checksum_ == filename.checksum()) {
+               LYXERR(Debug::FILES, "External modification but "
+                      "checksum unchanged: " << filename);
+diff --git a/src/support/FileMonitor.cpp b/src/support/FileMonitor.cpp
+index c703d2b..2a794f2 100644
+--- a/src/support/FileMonitor.cpp
++++ b/src/support/FileMonitor.cpp
+@@ -202,6 +202,42 @@ void FileMonitor::changed(bool const exists)
+ }
++FileMonitorBlocker FileMonitor::block(int delay)
++{
++      FileMonitorBlocker blocker = blocker_.lock();
++      if (!blocker)
++              blocker_ = blocker = make_shared<FileMonitorBlockerGuard>(this);
++      blocker->setDelay(delay);
++      return blocker;
++}
++
++
++FileMonitorBlockerGuard::FileMonitorBlockerGuard(FileMonitor * monitor)
++      : monitor_(monitor), delay_(0)
++{
++      QObject::disconnect(monitor->monitor_.get(), SIGNAL(fileChanged(bool)),
++                          monitor, SLOT(changed(bool)));
++}
++
++
++void FileMonitorBlockerGuard::setDelay(int delay)
++{
++      delay_ = max(delay_, delay);
++}
++
++
++FileMonitorBlockerGuard::~FileMonitorBlockerGuard()
++{
++      if (!monitor_)
++              return;
++      // Even if delay_ is 0, the QTimer is necessary. Indeed, the notifications
++      // from QFileSystemWatcher that we meant to ignore are not going to be
++      // treated immediately, so we must yield to give us the opportunity to
++      // ignore them.
++      QTimer::singleShot(delay_, monitor_, SLOT(connectToFileMonitorGuard()));
++}
++
++
+ ActiveFileMonitor::ActiveFileMonitor(std::shared_ptr<FileMonitorGuard> monitor,
+                                      FileName const & filename, int interval)
+       : FileMonitor(monitor), filename_(filename), interval_(interval),
+diff --git a/src/support/FileMonitor.h b/src/support/FileMonitor.h
+index 14aa834..fdf2bca 100644
+--- a/src/support/FileMonitor.h
++++ b/src/support/FileMonitor.h
+@@ -60,6 +60,12 @@ typedef std::unique_ptr<ActiveFileMonitor> ActiveFileMonitorPtr;
+ ///   monitor.connect(...);
+ /// (stops watching the first)
+ ///
++/// Block notifications for the duration of a scope:
++///   {
++///       FileMonitorBlocker block = monitor.block();
++///       ...
++///   }
++///
+ /// Reset connections:
+ ///   monitor.disconnect();
+ ///   or the disconnect method of the connection object for the boost signal.
+@@ -125,10 +131,27 @@ private:
+ };
++class FileMonitorBlockerGuard : public QObject
++{
++      Q_OBJECT
++      QPointer<FileMonitor> monitor_;
++      int delay_;
++
++public:
++      FileMonitorBlockerGuard(FileMonitor * monitor);
++      ~FileMonitorBlockerGuard();
++      void setDelay(int delay);
++};
++
++
++typedef std::shared_ptr<FileMonitorBlockerGuard> FileMonitorBlocker;
++
++
+ /// Main class
+ class FileMonitor : public QObject
+ {
+       Q_OBJECT
++      friend class FileMonitorBlockerGuard;
+ public:
+       FileMonitor(std::shared_ptr<FileMonitorGuard> monitor);
+@@ -142,6 +165,20 @@ public:
+       void disconnect();
+       /// absolute path being tracked
+       std::string const & filename() { return monitor_->filename(); }
++      /// Creates a guard that blocks notifications. Copyable. Notifications from
++      /// this monitor are blocked as long as there are copies of the
++      /// FileMonitorBlocker around.
++      /// \param delay is the amount waited in ms after expiration of the guard
++      /// before reconnecting. It can be used to slow down incoming events
++      /// accordingly. A value of 0 is still made asynchronous, because of the
++      /// fundamentally asynchronous nature of QFileSystemWatcher. To catch one's
++      /// own file operations, a value of 0 for delay is sufficient with the
++      /// inotify backend (e.g. Linux); for OSX (kqueue), a value of 100ms is
++      /// unsufficient and more tests need to be done in combination with
++      /// flushing/syncing to disk in order to understand how to catch one's own
++      /// operations reliably. No feedback about Windows. See
++      /// <https://www.mail-archive.com/lyx-devel@lists.lyx.org/msg200252.html>.
++      FileMonitorBlocker block(int delay = 0);
+       /// Make sure the good file is being monitored, after e.g. a move or a
+       /// deletion. See <https://bugreports.qt.io/browse/QTBUG-46483>. This is
+       /// called automatically.
+@@ -162,6 +199,8 @@ private:
+       sig fileChanged_;
+       /// the unique watch for our file
+       std::shared_ptr<FileMonitorGuard> const monitor_;
++      ///
++      std::weak_ptr<FileMonitorBlockerGuard> blocker_;
+ };
+
+commit ab4584d9a5747aad2c23cf7b26ee05a30de89bc9
+Author: Pavel Sanda <psanda@ucsd.edu>
+Date:   Thu Nov 16 09:22:11 2017 -0800
+
+    Revert b30161b591264f : If the external modification is a deletion, do not ask for reloading.
+
+diff --git a/src/Buffer.cpp b/src/Buffer.cpp
+index 6e37ee9..b83f872 100644
+--- a/src/Buffer.cpp
++++ b/src/Buffer.cpp
+@@ -380,15 +380,15 @@ public:
+       // Make sure the file monitor monitors the good file.
+       void refreshFileMonitor();
++      /// has it been notified of an external modification?
++      bool isExternallyModified() const { return externally_modified_; }
++
+       /// Notify or clear of external modification
+-      void fileExternallyModified(bool exists);
++      void fileExternallyModified(bool modified);
+       /// Block notifications of external modifications
+       FileMonitorBlocker blockFileMonitor() { return file_monitor_->block(); }
+-      /// has been externally modified? Can be reset by the user.
+-      mutable bool externally_modified_;
+-
+ private:
+       /// So we can force access via the accessors.
+       mutable Buffer const * parent_buffer;
+@@ -397,6 +397,9 @@ private:
+       int char_count_;
+       int blank_count_;
++      /// has been externally modified? Can be reset by the user.
++      mutable bool externally_modified_;
++
+       FileMonitorPtr file_monitor_;
+ };
+@@ -438,8 +441,9 @@ Buffer::Impl::Impl(Buffer * owner, FileName const & file, bool readonly_,
+         bibfile_cache_valid_(false), cite_labels_valid_(false), preview_error_(false),
+         inset(0), preview_loader_(0), cloned_buffer_(cloned_buffer),
+         clone_list_(0), doing_export(false),
+-        tracked_changes_present_(0), externally_modified_(false), parent_buffer(0),
+-        word_count_(0), char_count_(0), blank_count_(0)
++        tracked_changes_present_(0), parent_buffer(0),
++        word_count_(0), char_count_(0), blank_count_(0),
++        externally_modified_(false)
+ {
+       refreshFileMonitor();
+       if (!cloned_buffer_) {
+@@ -5338,29 +5342,26 @@ void Buffer::Impl::refreshFileMonitor()
+       // The previous file monitor is invalid
+       // This also destroys the previous file monitor and all its connections
+       file_monitor_ = FileSystemWatcher::monitor(filename);
++      fileExternallyModified(false);
+       // file_monitor_ will be destroyed with *this, so it is not going to call a
+       // destroyed object method.
+-      file_monitor_->connect([this](bool exists) {
+-                      fileExternallyModified(exists);
+-              });
++      file_monitor_->connect([this](){ fileExternallyModified(true); });
+ }
+ void Buffer::Impl::fileExternallyModified(bool const exists)
+ {
+-      // prevent false positives, because FileMonitorBlocker is not enough on
+-      // OSX.
+-      if (checksum_ == filename.checksum()) {
++      if (modified) {
++              // prevent false positives, because FileMonitorBlocker is not enough on
++              // OSX.
++              if (filename.exists() && checksum_ == filename.checksum()) {
+               LYXERR(Debug::FILES, "External modification but "
+-                     "checksum unchanged: " << filename);
++                      "checksum unchanged: " << filename);
+               return;
++              }
++              lyx_clean = bak_clean = false;
+       }
+-      lyx_clean = bak_clean = false;
+-      // If the file has been deleted, only mark the file as dirty since it is
+-      // pointless to prompt for reloading. If later a file is moved into this
+-      // location, then the externally modified warning will appear then.
+-      if (exists)
+-                      externally_modified_ = true;
++      externally_modified_ = modified;
+       // Update external modification notification.
+       // Dirty buffers must be visible at all times.
+       if (wa_ && wa_->unhide(owner_))
+@@ -5373,15 +5374,13 @@ void Buffer::Impl::fileExternallyModified(bool const exists)
+ bool Buffer::notifiesExternalModification() const
+ {
+-      return d->externally_modified_;
++      return d->isExternallyModified();
+ }
+ void Buffer::clearExternalModification() const
+ {
+-      d->externally_modified_ = false;
+-      if (d->wa_)
+-              d->wa_->updateTitles();
++      d->fileExternallyModified(false);
+ }
+diff --git a/src/graphics/GraphicsCacheItem.cpp b/src/graphics/GraphicsCacheItem.cpp
+index f54ce80..576ad92 100644
+--- a/src/graphics/GraphicsCacheItem.cpp
++++ b/src/graphics/GraphicsCacheItem.cpp
+@@ -220,7 +220,7 @@ void CacheItem::Impl::startMonitor()
+               return;
+       monitor_ = FileSystemWatcher::activeMonitor(filename_);
+       // Disconnected at the same time as this is destroyed.
+-      monitor_->connect([=](bool /* exists */){ startLoading(); });
++      monitor_->connect([=](){ startLoading(); });
+ }
+diff --git a/src/insets/RenderPreview.cpp b/src/insets/RenderPreview.cpp
+index df0ac64..18882fc 100644
+--- a/src/insets/RenderPreview.cpp
++++ b/src/insets/RenderPreview.cpp
+@@ -304,7 +304,7 @@ void RenderMonitoredPreview::startMonitoring() const
+ {
+       if (!monitoring()) {
+               monitor_ = FileSystemWatcher::activeMonitor(filename_);
+-              monitor_->connect([this](bool /* exists */){ changed_(); });
++              monitor_->connect(changed_);
+       }
+ }
+diff --git a/src/support/FileMonitor.cpp b/src/support/FileMonitor.cpp
+index 2a794f2..f1fefb8 100644
+--- a/src/support/FileMonitor.cpp
++++ b/src/support/FileMonitor.cpp
+@@ -118,37 +118,31 @@ FileMonitorGuard::~FileMonitorGuard()
+ }
+-void FileMonitorGuard::refresh(bool const emit)
++void FileMonitorGuard::refresh()
+ {
+       if (filename_.empty())
+               return;
+       QString const qfilename = toqstr(filename_);
+-      if (!qwatcher_->files().contains(qfilename)) {
+-              bool const existed = exists_;
+-              exists_ = QFile(qfilename).exists();
++      if(!qwatcher_->files().contains(qfilename)) {
++              bool exists = QFile(qfilename).exists();
+ #if (QT_VERSION >= 0x050000)
+-              if (exists_ && !qwatcher_->addPath(qfilename))
++              if (!exists || !qwatcher_->addPath(qfilename))
+ #else
+               auto add_path = [&]() {
+                       qwatcher_->addPath(qfilename);
+                       return qwatcher_->files().contains(qfilename);
+               };
+-              if (exists_ && !add_path())
++              if (!exists || !add_path())
+ #endif
+               {
+-                      LYXERR(Debug::FILES,
+-                             "Could not add path to QFileSystemWatcher: " << filename_);
+-                      QTimer::singleShot(5000, this, SLOT(refresh()));
+-              } else {
+-                      if (!exists_)
+-                              // The standard way to overwrite a file is to delete it and
+-                              // create a new file with the same name. Therefore if the file
+-                              // has just been deleted, it is smart to check not too long
+-                              // after whether it has been recreated.
+-                          QTimer::singleShot(existed ? 100 : 2000, this, SLOT(refresh()));
+-                      if (existed != exists_ && emit)
+-                              Q_EMIT fileChanged(exists_);
+-              }
++                      if (exists)
++                              LYXERR(Debug::FILES,
++                                     "Could not add path to QFileSystemWatcher: "
++                                     << filename_);
++                      QTimer::singleShot(2000, this, SLOT(refresh()));
++              } else if (exists && !exists_)
++                      Q_EMIT fileChanged();
++              setExists(exists);
+       }
+ }
+@@ -156,12 +150,11 @@ void FileMonitorGuard::refresh(bool const emit)
+ void FileMonitorGuard::notifyChange(QString const & path)
+ {
+       if (path == toqstr(filename_)) {
++              Q_EMIT fileChanged();
+               // If the file has been modified by delete-move, we are notified of the
+               // deletion but we no longer track the file. See
+               // <https://bugreports.qt.io/browse/QTBUG-46483> (not a bug).
+-              // Therefore we must refresh.
+-              refresh(false);
+-              Q_EMIT fileChanged(exists_);
++              refresh();
+       }
+ }
+@@ -169,15 +162,17 @@ void FileMonitorGuard::notifyChange(QString const & path)
+ FileMonitor::FileMonitor(std::shared_ptr<FileMonitorGuard> monitor)
+       : monitor_(monitor)
+ {
+-      connectToFileMonitorGuard();
++      QObject::connect(monitor_.get(), SIGNAL(fileChanged()),
++                       this, SLOT(changed()));
+       refresh();
+ }
+-void FileMonitor::connectToFileMonitorGuard()
++void FileMonitor::reconnectToFileMonitorGuard()
+ {
+-      QObject::connect(monitor_.get(), SIGNAL(fileChanged(bool)),
+-                       this, SLOT(changed(bool)));
++      monitor_->setExists(true);
++      QObject::connect(monitor_.get(), SIGNAL(fileChanged()),
++                       this, SLOT(changed()));
+ }
+@@ -190,15 +185,15 @@ signals2::connection FileMonitor::connect(slot const & slot)
+ void FileMonitor::disconnect()
+ {
+       fileChanged_.disconnect_all_slots();
+-      QObject::disconnect(this, SIGNAL(fileChanged(bool)));
++      QObject::disconnect(this, SIGNAL(fileChanged()));
+ }
+-void FileMonitor::changed(bool const exists)
++void FileMonitor::changed()
+ {
+       // emit boost signal
+-      fileChanged_(exists);
+-      Q_EMIT fileChanged(exists);
++      fileChanged_();
++      Q_EMIT fileChanged();
+ }
+@@ -215,8 +210,8 @@ FileMonitorBlocker FileMonitor::block(int delay)
+ FileMonitorBlockerGuard::FileMonitorBlockerGuard(FileMonitor * monitor)
+       : monitor_(monitor), delay_(0)
+ {
+-      QObject::disconnect(monitor->monitor_.get(), SIGNAL(fileChanged(bool)),
+-                          monitor, SLOT(changed(bool)));
++      QObject::disconnect(monitor->monitor_.get(), SIGNAL(fileChanged()),
++                          monitor, SLOT(changed()));
+ }
+@@ -234,7 +229,7 @@ FileMonitorBlockerGuard::~FileMonitorBlockerGuard()
+       // from QFileSystemWatcher that we meant to ignore are not going to be
+       // treated immediately, so we must yield to give us the opportunity to
+       // ignore them.
+-      QTimer::singleShot(delay_, monitor_, SLOT(connectToFileMonitorGuard()));
++      QTimer::singleShot(delay_, monitor_, SLOT(reconnectToFileMonitorGuard()));
+ }
+@@ -243,9 +238,8 @@ ActiveFileMonitor::ActiveFileMonitor(std::shared_ptr<FileMonitorGuard> monitor,
+       : FileMonitor(monitor), filename_(filename), interval_(interval),
+         timestamp_(0), checksum_(0), cooldown_(true)
+ {
+-      QObject::connect(this, SIGNAL(fileChanged(bool)), this, SLOT(setCooldown()));
++      QObject::connect(this, SIGNAL(fileChanged()), this, SLOT(setCooldown()));
+       QTimer::singleShot(interval_, this, SLOT(clearCooldown()));
+-      filename_.refresh();
+       if (!filename_.exists())
+               return;
+       timestamp_ = filename_.lastModified();
+@@ -260,9 +254,7 @@ void ActiveFileMonitor::checkModified()
+       cooldown_ = true;
+       bool changed = false;
+-      filename_.refresh();
+-      bool exists = filename_.exists();
+-      if (!exists) {
++      if (!filename_.exists()) {
+               changed = timestamp_ || checksum_;
+               timestamp_ = 0;
+               checksum_ = 0;
+@@ -280,7 +272,7 @@ void ActiveFileMonitor::checkModified()
+               }
+       }
+       if (changed)
+-              FileMonitor::changed(exists);
++              FileMonitor::changed();
+       QTimer::singleShot(interval_, this, SLOT(clearCooldown()));
+ }
+diff --git a/src/support/FileMonitor.h b/src/support/FileMonitor.h
+index fdf2bca..5e516bb 100644
+--- a/src/support/FileMonitor.h
++++ b/src/support/FileMonitor.h
+@@ -108,16 +108,18 @@ public:
+       ~FileMonitorGuard();
+       /// absolute path being tracked
+       std::string const & filename() { return filename_; }
++      /// if false, emit fileChanged() when we notice the existence of the file
++      void setExists(bool exists) { exists_ = exists; }
+ public Q_SLOTS:
+       /// Make sure it is being monitored, after e.g. a deletion. See
+       /// <https://bugreports.qt.io/browse/QTBUG-46483>. This is called
+       /// automatically.
+-      void refresh(bool emit = true);
++      void refresh();
+ Q_SIGNALS:
+       /// Connect to this to be notified when the file changes
+-      void fileChanged(bool exists) const;
++      void fileChanged() const;
+ private Q_SLOTS:
+       /// Receive notifications from the QFileSystemWatcher
+@@ -126,7 +128,6 @@ private Q_SLOTS:
+ private:
+       std::string const filename_;
+       QFileSystemWatcher * qwatcher_;
+-      /// for emitting fileChanged() when the file is created or deleted
+       bool exists_;
+ };
+@@ -156,7 +157,7 @@ class FileMonitor : public QObject
+ public:
+       FileMonitor(std::shared_ptr<FileMonitorGuard> monitor);
+-      typedef signals2::signal<void(bool)> sig;
++      typedef signals2::signal<void()> sig;
+       typedef sig::slot_type slot;
+       /// Connect and you'll be informed when the file has changed.
+       signals2::connection connect(slot const &);
+@@ -176,7 +177,7 @@ public:
+       /// inotify backend (e.g. Linux); for OSX (kqueue), a value of 100ms is
+       /// unsufficient and more tests need to be done in combination with
+       /// flushing/syncing to disk in order to understand how to catch one's own
+-      /// operations reliably. No feedback about Windows. See
++      /// operations reliably. No feedback from Windows yet. See
+       /// <https://www.mail-archive.com/lyx-devel@lists.lyx.org/msg200252.html>.
+       FileMonitorBlocker block(int delay = 0);
+       /// Make sure the good file is being monitored, after e.g. a move or a
+@@ -186,13 +187,13 @@ public:
+ Q_SIGNALS:
+       /// Connect to this to be notified when the file changes
+-      void fileChanged(bool exists) const;
++      void fileChanged() const;
+ protected Q_SLOTS:
+       /// Receive notifications from the FileMonitorGuard
+-      void changed(bool exists);
++      void changed();
+       ///
+-      void connectToFileMonitorGuard();
++      void reconnectToFileMonitorGuard();
+ private:
+       /// boost signal
+
+commit f1c415f3b0ae9ddea5548742f5300e86e95480f2
+Author: Pavel Sanda <psanda@ucsd.edu>
+Date:   Thu Nov 16 09:24:31 2017 -0800
+
+    Revert 2058faaa3bd: Prevent false positives in external modifications
+
+diff --git a/src/Buffer.cpp b/src/Buffer.cpp
+index b83f872..48391f9 100644
+--- a/src/Buffer.cpp
++++ b/src/Buffer.cpp
+@@ -387,7 +387,7 @@ public:
+       void fileExternallyModified(bool modified);
+       /// Block notifications of external modifications
+-      FileMonitorBlocker blockFileMonitor() { return file_monitor_->block(); }
++      FileMonitorBlocker blockFileMonitor() { return file_monitor_->block(10); }
+ private:
+       /// So we can force access via the accessors.
+@@ -5351,16 +5351,8 @@ void Buffer::Impl::refreshFileMonitor()
+ void Buffer::Impl::fileExternallyModified(bool const exists)
+ {
+-      if (modified) {
+-              // prevent false positives, because FileMonitorBlocker is not enough on
+-              // OSX.
+-              if (filename.exists() && checksum_ == filename.checksum()) {
+-              LYXERR(Debug::FILES, "External modification but "
+-                      "checksum unchanged: " << filename);
+-              return;
+-              }
++      if (modified) 
+               lyx_clean = bak_clean = false;
+-      }
+       externally_modified_ = modified;
+       // Update external modification notification.
+       // Dirty buffers must be visible at all times.
+diff --git a/src/support/FileMonitor.h b/src/support/FileMonitor.h
+index 5e516bb..49f12cb 100644
+--- a/src/support/FileMonitor.h
++++ b/src/support/FileMonitor.h
+@@ -167,18 +167,11 @@ public:
+       /// absolute path being tracked
+       std::string const & filename() { return monitor_->filename(); }
+       /// Creates a guard that blocks notifications. Copyable. Notifications from
+-      /// this monitor are blocked as long as there are copies of the
+-      /// FileMonitorBlocker around.
++      /// this monitor are blocked as long as there are copies around.
+       /// \param delay is the amount waited in ms after expiration of the guard
+-      /// before reconnecting. It can be used to slow down incoming events
+-      /// accordingly. A value of 0 is still made asynchronous, because of the
+-      /// fundamentally asynchronous nature of QFileSystemWatcher. To catch one's
+-      /// own file operations, a value of 0 for delay is sufficient with the
+-      /// inotify backend (e.g. Linux); for OSX (kqueue), a value of 100ms is
+-      /// unsufficient and more tests need to be done in combination with
+-      /// flushing/syncing to disk in order to understand how to catch one's own
+-      /// operations reliably. No feedback from Windows yet. See
+-      /// <https://www.mail-archive.com/lyx-devel@lists.lyx.org/msg200252.html>.
++      /// before reconnecting. This delay thing is to deal with asynchronous
++      /// notifications in a not so elegant fashion. But it can also be used to
++      /// slow down incoming events.
+       FileMonitorBlocker block(int delay = 0);
+       /// Make sure the good file is being monitored, after e.g. a move or a
+       /// deletion. See <https://bugreports.qt.io/browse/QTBUG-46483>. This is
+
+commit 96a893b5564404f80a2fd42b7a559d3306babce2
+Author: Pavel Sanda <psanda@ucsd.edu>
+Date:   Thu Nov 16 09:25:19 2017 -0800
+
+    Revert db581113: roperly track the lifetime of signals2::slots (#8261)
+
+diff --git a/src/Converter.cpp b/src/Converter.cpp
+index 664a4bb..6e26ed2 100644
+--- a/src/Converter.cpp
++++ b/src/Converter.cpp
+@@ -786,6 +786,20 @@ bool Converters::scanLog(Buffer const & buffer, string const & /*command*/,
+ }
++namespace {
++
++class ShowMessage
++      : public boost::signals2::trackable {
++public:
++      ShowMessage(Buffer const & b) : buffer_(b) {}
++      void operator()(docstring const & msg) const { buffer_.message(msg); }
++private:
++      Buffer const & buffer_;
++};
++
++}
++
++
+ bool Converters::runLaTeX(Buffer const & buffer, string const & command,
+                         OutputParams const & runparams, ErrorList & errorList)
+ {
+@@ -798,12 +812,8 @@ bool Converters::runLaTeX(Buffer const & buffer, string const & command,
+                   buffer.filePath(), buffer.layoutPos(),
+                   buffer.lastPreviewError());
+       TeXErrors terr;
+-      // The connection closes itself at the end of the scope when latex is
+-      // destroyed. One cannot close (and destroy) buffer while the converter is
+-      // running.
+-      latex.message.connect([&buffer](docstring const & msg){
+-                      buffer.message(msg);
+-              });
++      ShowMessage show(buffer);
++      latex.message.connect(show);
+       int const result = latex.run(terr);
+       if (result & LaTeX::ERRORS)
+diff --git a/src/LaTeX.h b/src/LaTeX.h
+index 0b46c60..b2d6ac0 100644
+--- a/src/LaTeX.h
++++ b/src/LaTeX.h
+@@ -18,7 +18,8 @@
+ #include "support/docstring.h"
+ #include "support/FileName.h"
+-#include "support/signals.h"
++
++#include <boost/signals2.hpp>
+ #include <vector>
+ #include <set>
+@@ -147,7 +148,7 @@ public:
+       };
+       /// This signal emits an informative message
+-      signals2::signal<void(docstring)> message;
++      boost::signals2::signal<void(docstring)> message;
+       /**
+diff --git a/src/Server.cpp b/src/Server.cpp
+index 8953c78..debb8a9 100644
+--- a/src/Server.cpp
++++ b/src/Server.cpp
+@@ -55,7 +55,8 @@
+ #include "support/lassert.h"
+ #include "support/lstrings.h"
+ #include "support/os.h"
+-#include "support/signals.h"
++
++#include "support/bind.h"
+ #include <iostream>
+@@ -858,12 +859,8 @@ int LyXComm::startPipe(string const & file, bool write)
+       }
+       if (!write) {
+-              // Make sure not to call read_ready after destruction.
+-              weak_ptr<void> tracker = tracker_.p();
+-              theApp()->registerSocketCallback(fd, [=](){
+-                              if (!tracker.expired())
+-                                      read_ready();
+-                      });
++              theApp()->registerSocketCallback(fd,
++                      bind(&LyXComm::read_ready, this));
+       }
+       return fd;
+diff --git a/src/Server.h b/src/Server.h
+index 40021da..1a46c89 100644
+--- a/src/Server.h
++++ b/src/Server.h
+@@ -14,7 +14,7 @@
+ #ifndef SERVER_H
+ #define SERVER_H
+-#include "support/signals.h"
++#include <boost/signals2/trackable.hpp>
+ #include <vector>
+@@ -30,7 +30,7 @@ namespace lyx {
+ class Server;
+-/** This class manages the pipes used for communicating with clients.
++/** This class managed the pipes used for communicating with clients.
+  Usage: Initialize with pipe-filename-base, client class to receive
+  messages, and callback-function that will be called with the messages.
+  When you want to send, use "send()".
+@@ -38,7 +38,7 @@ class Server;
+  a clean string interface.
+  */
+ #ifndef _WIN32
+-class LyXComm {
++class LyXComm : public boost::signals2::trackable {
+ #else
+ class LyXComm : public QObject {
+       Q_OBJECT
+@@ -189,9 +189,6 @@ private:
+       /// Did we defer loading of files to another instance?
+       bool deferred_loading_;
+-
+-      /// Track object's liveness
+-      support::Trackable tracker_;
+ };
+diff --git a/src/frontends/qt4/GuiView.cpp b/src/frontends/qt4/GuiView.cpp
+index c587460..68ef3b9 100644
+--- a/src/frontends/qt4/GuiView.cpp
++++ b/src/frontends/qt4/GuiView.cpp
+@@ -529,8 +529,7 @@ GuiView::GuiView(int id)
+       // Start autosave timer
+       if (lyxrc.autosave) {
+-              // The connection is closed when this is destroyed.
+-              d.autosave_timeout_.timeout.connect([this](){ autoSave();});
++              d.autosave_timeout_.timeout.connect(bind(&GuiView::autoSave, this));
+               d.autosave_timeout_.setTimeout(lyxrc.autosave * 1000);
+               d.autosave_timeout_.start();
+       }
+diff --git a/src/frontends/qt4/GuiWorkArea.cpp b/src/frontends/qt4/GuiWorkArea.cpp
+index fe7082d..d7c7b00 100644
+--- a/src/frontends/qt4/GuiWorkArea.cpp
++++ b/src/frontends/qt4/GuiWorkArea.cpp
+@@ -320,10 +320,9 @@ void GuiWorkArea::init()
+       d->setCursorShape(Qt::IBeamCursor);
+-      // This connection is closed at the same time as this is destroyed.
+-      d->synthetic_mouse_event_.timeout.timeout.connect([this](){
+-                      generateSyntheticMouseEvent();
+-              });
++      d->synthetic_mouse_event_.timeout.timeout.connect(
++              bind(&GuiWorkArea::generateSyntheticMouseEvent,
++                                      this));
+       LYXERR(Debug::GUI, "viewport width: " << viewport()->width()
+               << "  viewport height: " << viewport()->height());
+diff --git a/src/graphics/GraphicsCacheItem.cpp b/src/graphics/GraphicsCacheItem.cpp
+index 576ad92..306dcdb 100644
+--- a/src/graphics/GraphicsCacheItem.cpp
++++ b/src/graphics/GraphicsCacheItem.cpp
+@@ -29,6 +29,7 @@
+ #include "support/lassert.h"
+ #include "support/unique_ptr.h"
++#include "support/bind.h"
+ #include "support/TempFile.h"
+ using namespace std;
+@@ -38,7 +39,7 @@ namespace lyx {
+ namespace graphics {
+-class CacheItem::Impl {
++class CacheItem::Impl : public boost::signals2::trackable {
+ public:
+       ///
+@@ -49,7 +50,7 @@ public:
+       /**
+        *  If no file conversion is needed, then tryDisplayFormat() calls
+        *  loadImage() directly.
+-       * \return true if a conversion is necessary and no error occurred.
++       * \return true if a conversion is necessary and no error occurred. 
+        */
+       bool tryDisplayFormat(FileName & filename, string & from);
+@@ -119,7 +120,10 @@ public:
+       ImageStatus status_;
+       /// This signal is emitted when the image loading status changes.
+-      signals2::signal<void()> statusChanged;
++      boost::signals2::signal<void()> statusChanged;
++
++      /// The connection of the signal ConvProcess::finishedConversion,
++      boost::signals2::connection cc_;
+       ///
+       unique_ptr<Converter> converter_;
+@@ -195,7 +199,7 @@ ImageStatus CacheItem::status() const
+ }
+-signals2::connection CacheItem::connect(slot_type const & slot) const
++boost::signals2::connection CacheItem::connect(slot_type const & slot) const
+ {
+       return pimpl_->statusChanged.connect(slot);
+ }
+@@ -219,7 +223,6 @@ void CacheItem::Impl::startMonitor()
+       if (monitor_)
+               return;
+       monitor_ = FileSystemWatcher::activeMonitor(filename_);
+-      // Disconnected at the same time as this is destroyed.
+       monitor_->connect([=](){ startLoading(); });
+ }
+@@ -251,6 +254,9 @@ void CacheItem::Impl::reset()
+       status_ = WaitingToLoad;
++      if (cc_.connected())
++              cc_.disconnect();
++
+       if (converter_)
+               converter_.reset();
+ }
+@@ -274,6 +280,7 @@ void CacheItem::Impl::imageConverted(bool success)
+       file_to_load_ = converter_ ? FileName(converter_->convertedFile())
+                                      : FileName();
+       converter_.reset();
++      cc_.disconnect();
+       success = !file_to_load_.empty() && file_to_load_.isReadableFile();
+@@ -442,13 +449,9 @@ void CacheItem::Impl::convertToDisplayFormat()
+       // Connect a signal to this->imageConverted and pass this signal to
+       // the graphics converter so that we can load the modified file
+       // on completion of the conversion process.
+-      converter_ = make_unique<Converter>(doc_file_, filename,
+-                                          to_file_base.absFileName(),
++      converter_ = make_unique<Converter>(doc_file_, filename, to_file_base.absFileName(),
+                                           from, to_);
+-      // Connection is closed at the same time as *this is destroyed.
+-      converter_->connect([this](bool success){
+-                      imageConverted(success);
+-              });
++      converter_->connect(bind(&Impl::imageConverted, this, _1));
+       converter_->startConversion();
+ }
+diff --git a/src/graphics/GraphicsCacheItem.h b/src/graphics/GraphicsCacheItem.h
+index 6f7f968..9cee2b8 100644
+--- a/src/graphics/GraphicsCacheItem.h
++++ b/src/graphics/GraphicsCacheItem.h
+@@ -30,7 +30,7 @@
+ #include "GraphicsTypes.h"
+-#include "support/signals.h"
++#include <boost/signals2.hpp>
+ namespace lyx {
+@@ -82,9 +82,9 @@ public:
+       /** Connect and you'll be informed when the loading status of the image
+        *  changes.
+        */
+-      typedef signals2::signal<void()>::slot_type slot_type;
++      typedef boost::signals2::signal<void()>::slot_type slot_type;
+       ///
+-      signals2::connection connect(slot_type const &) const;
++      boost::signals2::connection connect(slot_type const &) const;
+ private:
+       /// noncopyable
+diff --git a/src/graphics/GraphicsConverter.cpp b/src/graphics/GraphicsConverter.cpp
+index 598e108..63b6a44 100644
+--- a/src/graphics/GraphicsConverter.cpp
++++ b/src/graphics/GraphicsConverter.cpp
+@@ -27,6 +27,7 @@
+ #include "support/lstrings.h"
+ #include "support/os.h"
++#include "support/bind.h"
+ #include "support/TempFile.h"
+ #include <sstream>
+@@ -39,12 +40,10 @@ namespace lyx {
+ namespace graphics {
+-class Converter::Impl {
++class Converter::Impl : public boost::signals2::trackable {
+ public:
+       ///
+-      Impl(FileName const & doc_fname,
+-           FileName const & from_file, string const & to_file_base,
+-           string const & from_format, string const & to_format);
++      Impl(FileName const &, FileName const &, string const &, string const &, string const &);
+       ///
+       void startConversion();
+@@ -59,9 +58,9 @@ public:
+       /** At the end of the conversion process inform the outside world
+        *  by emitting a signal.
+        */
+-      typedef signals2::signal<void(bool)> sig;
++      typedef boost::signals2::signal<void(bool)> SignalType;
+       ///
+-      sig finishedConversion;
++      SignalType finishedConversion;
+       ///
+       FileName const doc_fname_;
+@@ -75,8 +74,6 @@ public:
+       bool valid_process_;
+       ///
+       bool finished_;
+-      ///
+-      Trackable tracker_;
+ };
+@@ -88,8 +85,8 @@ bool Converter::isReachable(string const & from_format_name,
+ Converter::Converter(FileName const & doc_fname,
+-                     FileName const & from_file, string const & to_file_base,
+-                     string const & from_format, string const & to_format)
++                   FileName const & from_file, string const & to_file_base,
++                   string const & from_format, string const & to_format)
+       : pimpl_(new Impl(doc_fname, from_file, to_file_base, from_format, to_format))
+ {}
+@@ -106,7 +103,7 @@ void Converter::startConversion() const
+ }
+-signals2::connection Converter::connect(slot_type const & slot) const
++boost::signals2::connection Converter::connect(slot_type const & slot) const
+ {
+       return pimpl_->finishedConversion.connect(slot);
+ }
+@@ -191,10 +188,9 @@ void Converter::Impl::startConversion()
+               return;
+       }
+-      ForkedCall::sigPtr ptr = ForkedCallQueue::add(script_command_);
+-      ptr->connect(ForkedCall::slot([this](pid_t pid, int retval){
+-                              converted(pid, retval);
+-                      }).track_foreign(tracker_.p()));
++      ForkedCall::SignalTypePtr ptr =
++              ForkedCallQueue::add(script_command_);
++      ptr->connect(bind(&Impl::converted, this, _1, _2));
+ }
+diff --git a/src/graphics/GraphicsConverter.h b/src/graphics/GraphicsConverter.h
+index c038029..d3d0b81 100644
+--- a/src/graphics/GraphicsConverter.h
++++ b/src/graphics/GraphicsConverter.h
+@@ -17,8 +17,7 @@
+ #ifndef GRAPHICSCONVERTER_H
+ #define GRAPHICSCONVERTER_H
+-#include "support/signals.h"
+-
++#include <boost/signals2.hpp>
+ namespace lyx {
+@@ -48,12 +47,11 @@ public:
+       /** Connect and you'll be informed when the conversion process has
+        *  finished.
+        *  If the conversion is successful, then the listener is passed \c true.
+-       *  The connection is closed when this is destroyed.
+        */
+-      typedef signals2::signal<void(bool)> sig_type;
++      typedef boost::signals2::signal<void(bool)> sig_type;
+       typedef sig_type::slot_type slot_type;
+       ///
+-      signals2::connection connect(slot_type const &) const;
++      boost::signals2::connection connect(slot_type const &) const;
+       /** If the conversion is successful, this returns the name of the
+        *  resulting file.
+diff --git a/src/graphics/GraphicsLoader.cpp b/src/graphics/GraphicsLoader.cpp
+index 683f092..3503aba 100644
+--- a/src/graphics/GraphicsLoader.cpp
++++ b/src/graphics/GraphicsLoader.cpp
+@@ -107,17 +107,16 @@ void LoaderQueue::loadNext()
+ LoaderQueue::LoaderQueue() : timer(s_millisecs_, Timeout::ONETIME),
+-                             running_(false)
++                           running_(false)
+ {
+-      // Disconnected when this is destroyed
+-      timer.timeout.connect([this](){ loadNext(); });
++      timer.timeout.connect(bind(&LoaderQueue::loadNext, this));
+ }
+ void LoaderQueue::startLoader()
+ {
+       LYXERR(Debug::GRAPHICS, "LoaderQueue: waking up");
+-      running_ = true;
++      running_ = true ;
+       timer.setTimeout(s_millisecs_);
+       timer.start();
+ }
+@@ -164,7 +163,7 @@ void LoaderQueue::touch(Cache::ItemPtr const & item)
+ typedef std::shared_ptr<Image> ImagePtr;
+-class Loader::Impl {
++class Loader::Impl : public boost::signals2::trackable {
+       friend class Loader;
+ public:
+       ///
+@@ -193,9 +192,9 @@ public:
+       /// We modify a local copy of the image once it is loaded.
+       ImagePtr image_;
+       /// This signal is emitted when the image loading status changes.
+-      signals2::signal<void()> signal_;
+-      /// The connection of the signal statusChanged
+-      signals2::scoped_connection connection_;
++      boost::signals2::signal<void()> signal_;
++      /// The connection of the signal StatusChanged  
++      boost::signals2::connection sc_;
+       double displayPixelRatio() const
+       {
+@@ -364,7 +363,7 @@ void Loader::setDisplayPixelRatio(double scale)
+ }
+-signals2::connection Loader::connect(slot const & slot) const
++boost::signals2::connection Loader::connect(slot_type const & slot) const
+ {
+       return pimpl_->signal_.connect(slot);
+ }
+@@ -406,7 +405,7 @@ void Loader::Impl::resetFile(FileName const & file)
+               // signal needs to be disconnected.
+               try {
+                       // This can in theory throw a BufferException
+-                      connection_.disconnect();
++                      sc_.disconnect();
+               } catch (...) {
+                       LYXERR(Debug::GRAPHICS, "Unable to disconnect signal.");
+               }
+@@ -435,8 +434,7 @@ void Loader::Impl::resetFile(FileName const & file)
+       if (continue_monitoring && !cached_item_->monitoring())
+               cached_item_->startMonitoring();
+-      // This is a scoped connection
+-      connection_ = cached_item_->connect([this](){ statusChanged(); });
++      sc_ = cached_item_->connect(bind(&Impl::statusChanged, this));
+ }
+diff --git a/src/graphics/GraphicsLoader.h b/src/graphics/GraphicsLoader.h
+index 0a299cb..62ea303 100644
+--- a/src/graphics/GraphicsLoader.h
++++ b/src/graphics/GraphicsLoader.h
+@@ -26,7 +26,7 @@
+ #include "GraphicsTypes.h"
+-#include "support/signals.h"
++#include <boost/signals2.hpp>
+ namespace lyx {
+@@ -70,7 +70,7 @@ public:
+        */
+       void startLoading() const;
+-      /** Tries to reload the image.
++      /** Tries to reload the image. 
+        */
+       void reload() const;
+@@ -90,10 +90,10 @@ public:
+       /** Connect and you'll be informed when the loading status of the image
+        *  changes.
+        */
+-      typedef signals2::signal<void()> sig;
+-      typedef sig::slot_type slot;
++      typedef boost::signals2::signal<void()> sig_type;
++      typedef sig_type::slot_type slot_type;
+       ///
+-      signals2::connection connect(slot const &) const;
++      boost::signals2::connection connect(slot_type const &) const;
+       /** The loaded image with Pixmap set.
+        *  If the Pixmap is not yet set (see status() for why...), returns 0.
+diff --git a/src/graphics/PreviewImage.cpp b/src/graphics/PreviewImage.cpp
+index b80bf94..da0f1e2 100644
+--- a/src/graphics/PreviewImage.cpp
++++ b/src/graphics/PreviewImage.cpp
+@@ -20,6 +20,7 @@
+ #include "support/FileName.h"
++#include "support/bind.h"
+ using namespace std;
+ using namespace lyx::support;
+@@ -27,7 +28,7 @@ using namespace lyx::support;
+ namespace lyx {
+ namespace graphics {
+-class PreviewImage::Impl {
++class PreviewImage::Impl : public boost::signals2::trackable {
+ public:
+       ///
+       Impl(PreviewImage & p, PreviewLoader & l,
+@@ -104,14 +105,15 @@ PreviewLoader & PreviewImage::previewLoader() const
+ }
+-PreviewImage::Impl::Impl(PreviewImage & p, PreviewLoader & l, string const & s,
+-                         FileName const & bf, double af)
++PreviewImage::Impl::Impl(PreviewImage & p, PreviewLoader & l,
++                       string const & s,
++                       FileName const & bf,
++                       double af)
+       : parent_(p), ploader_(l), iloader_(l.buffer().fileName(), bf),
+         snippet_(s), ascent_frac_(af)
+ {
+       iloader_.setDisplayPixelRatio(l.displayPixelRatio());
+-      // This connection is destroyed at the same time as this.
+-      iloader_.connect([this](){ statusChanged(); });
++      iloader_.connect(bind(&Impl::statusChanged, this));
+ }
+diff --git a/src/graphics/PreviewLoader.cpp b/src/graphics/PreviewLoader.cpp
+index 22b0f23..c6f4d06 100644
+--- a/src/graphics/PreviewLoader.cpp
++++ b/src/graphics/PreviewLoader.cpp
+@@ -38,6 +38,7 @@
+ #include "support/ForkedCalls.h"
+ #include "support/lstrings.h"
++#include "support/bind.h"
+ #include "support/TempFile.h"
+ #include <atomic>
+@@ -166,7 +167,7 @@ typedef InProgressProcesses::value_type InProgressProcess;
+ namespace lyx {
+ namespace graphics {
+-class PreviewLoader::Impl {
++class PreviewLoader::Impl : public boost::signals2::trackable {
+ public:
+       ///
+       Impl(PreviewLoader & p, Buffer const & b);
+@@ -187,7 +188,7 @@ public:
+       void refreshPreviews();
+       /// Emit this signal when an image is ready for display.
+-      signals2::signal<void(PreviewImage const &)> imageReady;
++      boost::signals2::signal<void(PreviewImage const &)> imageReady;
+       Buffer const & buffer() const { return buffer_; }
+@@ -238,8 +239,6 @@ private:
+       /// We don't own this
+       static lyx::Converter const * pconverter_;
+-
+-      signals2::scoped_connection connection_;
+ };
+@@ -297,7 +296,7 @@ void PreviewLoader::refreshPreviews()
+ }
+-signals2::connection PreviewLoader::connect(slot const & slot) const
++boost::signals2::connection PreviewLoader::connect(slot_type const & slot) const
+ {
+       return pimpl_->imageReady.connect(slot);
+ }
+@@ -708,12 +707,12 @@ void PreviewLoader::Impl::startLoading(bool wait)
+          << " " << quoteName(latexfile.toFilesystemEncoding())
+          << " --dpi " << font_scaling_factor_;
+-      // FIXME XHTML
++      // FIXME XHTML 
+       // The colors should be customizable.
+       if (!buffer_.isExporting()) {
+               ColorCode const fg = PreviewLoader::foregroundColor();
+               ColorCode const bg = PreviewLoader::backgroundColor();
+-              cs << " --fg " << theApp()->hexName(fg)
++              cs << " --fg " << theApp()->hexName(fg) 
+                  << " --bg " << theApp()->hexName(bg);
+       }
+@@ -737,11 +736,9 @@ void PreviewLoader::Impl::startLoading(bool wait)
+       }
+       // Initiate the conversion from LaTeX to bitmap images files.
+-      ForkedCall::sigPtr convert_ptr = make_shared<ForkedCall::sig>();
+-      // This is a scoped connection
+-      connection_ = convert_ptr->connect([this](pid_t pid, int retval){
+-                      finishedGenerating(pid, retval);
+-              });
++      ForkedCall::SignalTypePtr
++              convert_ptr(new ForkedCall::SignalType);
++      convert_ptr->connect(bind(&Impl::finishedGenerating, this, _1, _2));
+       ForkedCall call(buffer_.filePath());
+       int ret = call.startScript(command, convert_ptr);
+diff --git a/src/graphics/PreviewLoader.h b/src/graphics/PreviewLoader.h
+index ca22a9f..3239ffc 100644
+--- a/src/graphics/PreviewLoader.h
++++ b/src/graphics/PreviewLoader.h
+@@ -18,8 +18,7 @@
+ #ifndef PREVIEWLOADER_H
+ #define PREVIEWLOADER_H
+-#include "support/signals.h"
+-
++#include <boost/signals2.hpp>
+ #include <QObject>
+ #include "ColorCode.h"
+@@ -77,10 +76,10 @@ public:
+        *  has been created and is ready for loading through
+        *  lyx::graphics::PreviewImage::image().
+        */
+-      typedef signals2::signal<void(PreviewImage const &)> sig;
+-      typedef sig::slot_type slot;
++      typedef boost::signals2::signal<void(PreviewImage const &)> sig_type;
++      typedef sig_type::slot_type slot_type;
+       ///
+-      signals2::connection connect(slot const &) const;
++      boost::signals2::connection connect(slot_type const &) const;
+       /** When PreviewImage has finished loading the image file into memory,
+        *  it tells the PreviewLoader to tell the outside world
+diff --git a/src/insets/InsetExternal.cpp b/src/insets/InsetExternal.cpp
+index 1f0f5f2..e1130bf 100644
+--- a/src/insets/InsetExternal.cpp
++++ b/src/insets/InsetExternal.cpp
+@@ -39,6 +39,7 @@
+ #include "graphics/PreviewLoader.h"
++#include "support/bind.h"
+ #include "support/convert.h"
+ #include "support/debug.h"
+ #include "support/ExceptionMessage.h"
+@@ -426,6 +427,7 @@ InsetExternal::InsetExternal(Buffer * buf)
+ // Mouse hover is not copied and remains empty
+ InsetExternal::InsetExternal(InsetExternal const & other)
+       : Inset(other),
++        boost::signals2::trackable(),
+         params_(other.params_),
+         renderer_(other.renderer_->clone(this))
+ {}
+@@ -652,7 +654,6 @@ void InsetExternal::updatePreview() const
+       case PREVIEW_INSTANT: {
+               renderer_ = make_unique<RenderMonitoredPreview>(this);
+               RenderMonitoredPreview * preview_ptr = renderer_->asMonitoredPreview();
+-              // This connection is closed at the same time as this is destroyed.
+               preview_ptr->connect([=]() { fileChanged(); });
+               add_preview_and_start_loading(*preview_ptr, *this, buffer());
+               break;
+diff --git a/src/insets/InsetExternal.h b/src/insets/InsetExternal.h
+index 75b7f70..4a15be1 100644
+--- a/src/insets/InsetExternal.h
++++ b/src/insets/InsetExternal.h
+@@ -19,6 +19,8 @@
+ #include "support/FileName.h"
+ #include "support/unique_ptr.h"
++#include <boost/signals2/trackable.hpp>
++
+ namespace lyx {
+@@ -88,7 +90,7 @@ private:
+ class RenderBase;
+ ///
+-class InsetExternal : public Inset
++class InsetExternal : public Inset, public boost::signals2::trackable
+ {
+       // Disable assignment operator, since it is not used, and it is too
+       // complicated to implement it consistently with the copy constructor
+diff --git a/src/insets/RenderPreview.cpp b/src/insets/RenderPreview.cpp
+index 18882fc..948ddb9 100644
+--- a/src/insets/RenderPreview.cpp
++++ b/src/insets/RenderPreview.cpp
+@@ -31,6 +31,8 @@
+ #include "support/lassert.h"
+ #include "support/lstrings.h"
++#include "support/bind.h"
++
+ using namespace std;
+ using namespace lyx::support;
+@@ -75,11 +77,19 @@ RenderPreview::RenderPreview(Inset const * inset)
+ RenderPreview::RenderPreview(RenderPreview const & other,
+                            Inset const * inset)
+       : RenderBase(other),
++        boost::signals2::trackable(),
+         snippet_(other.snippet_),
+         parent_(inset)
+ {}
++RenderPreview::~RenderPreview()
++{
++      if (ploader_connection_.connected())
++              ploader_connection_.disconnect();
++}
++
++
+ RenderBase * RenderPreview::clone(Inset const * inset) const
+ {
+       return new RenderPreview(*this, inset);
+@@ -231,12 +241,10 @@ void RenderPreview::addPreview(docstring const & latex_snippet,
+       // If this is the first time of calling, connect to the
+       // PreviewLoader signal that'll inform us when the preview image
+       // is ready for loading.
+-      if (!ploader_connection_.connected())
+-              // This is a scoped connection.
+-              ploader_connection_ =
+-                      ploader.connect([this](graphics::PreviewImage const & pi){
+-                              imageReady(pi);
+-                      });
++      if (!ploader_connection_.connected()) {
++              ploader_connection_ = ploader.connect(
++                      bind(&RenderPreview::imageReady, this, _1));
++      }
+       ploader.add(snippet_);
+ }
+@@ -288,7 +296,8 @@ void RenderMonitoredPreview::draw(PainterInfo & pi, int x, int y) const
+ }
+-signals2::connection RenderMonitoredPreview::connect(slot const & slot)
++boost::signals2::connection
++RenderMonitoredPreview::connect(ChangedSig::slot_type const & slot)
+ {
+       return changed_.connect(slot);
+ }
+diff --git a/src/insets/RenderPreview.h b/src/insets/RenderPreview.h
+index 2f83aff..42d944d 100644
+--- a/src/insets/RenderPreview.h
++++ b/src/insets/RenderPreview.h
+@@ -21,8 +21,10 @@
+ #include "support/docstring.h"
+ #include "support/FileMonitor.h"
+ #include "support/FileName.h"
+-#include "support/signals.h"
++#include <boost/signals2.hpp>
++#include <boost/signals2/trackable.hpp>
++#include <boost/signals2/connection.hpp>
+ namespace lyx {
+@@ -38,7 +40,7 @@ class PreviewLoader;
+ } // namespace graphics
+-class RenderPreview : public RenderBase {
++class RenderPreview : public RenderBase, public boost::signals2::trackable {
+ public:
+       /// Return true if preview is enabled in text (from LyXRC::preview)
+       static bool previewText();
+@@ -47,6 +49,7 @@ public:
+       RenderPreview(Inset const *);
+       RenderPreview(RenderPreview const &, Inset const *);
++      ~RenderPreview();
+       RenderBase * clone(Inset const *) const;
+       /// Compute the size of the object, returned in dim
+@@ -101,7 +104,7 @@ private:
+       /** Store the connection to the preview loader so that we connect
+        *  only once.
+        */
+-      signals2::scoped_connection ploader_connection_;
++      boost::signals2::connection ploader_connection_;
+       /// Inform the core that the inset has changed.
+       Inset const * parent_;
+@@ -121,17 +124,15 @@ public:
+       void stopMonitoring() const;
+       /// Connect and you'll be informed when the file changes.
+-      /// Do not forget to track objects used by the slot.
+-      typedef signals2::signal<void()> sig;
+-      typedef sig::slot_type slot;
+-      signals2::connection connect(slot const & slot);
++      typedef boost::signals2::signal<void()> ChangedSig;
++      boost::signals2::connection connect(ChangedSig::slot_type const &);
+       /// equivalent to dynamic_cast
+       virtual RenderMonitoredPreview * asMonitoredPreview() { return this; }
+ private:
+       /// This signal is emitted if the file is modified
+-      sig changed_;
++      ChangedSig changed_;
+       ///
+       mutable support::ActiveFileMonitorPtr monitor_;
+       ///
+diff --git a/src/support/FileMonitor.cpp b/src/support/FileMonitor.cpp
+index f1fefb8..30a4170 100644
+--- a/src/support/FileMonitor.cpp
++++ b/src/support/FileMonitor.cpp
+@@ -176,7 +176,8 @@ void FileMonitor::reconnectToFileMonitorGuard()
+ }
+-signals2::connection FileMonitor::connect(slot const & slot)
++boost::signals2::connection
++FileMonitor::connect(sig::slot_type const & slot)
+ {
+       return fileChanged_.connect(slot);
+ }
+diff --git a/src/support/FileMonitor.h b/src/support/FileMonitor.h
+index 49f12cb..23302ed 100644
+--- a/src/support/FileMonitor.h
++++ b/src/support/FileMonitor.h
+@@ -17,7 +17,6 @@
+ #define FILEMONITOR_H
+ #include "support/FileName.h"
+-#include "support/signals.h"
+ #include <memory>
+@@ -25,6 +24,8 @@
+ #include <QObject>
+ #include <QPointer>
++#include <boost/signals2.hpp>
++
+ namespace lyx {
+ namespace support {
+@@ -157,10 +158,9 @@ class FileMonitor : public QObject
+ public:
+       FileMonitor(std::shared_ptr<FileMonitorGuard> monitor);
+-      typedef signals2::signal<void()> sig;
+-      typedef sig::slot_type slot;
++      typedef boost::signals2::signal<void()> sig;
+       /// Connect and you'll be informed when the file has changed.
+-      signals2::connection connect(slot const &);
++      boost::signals2::connection connect(sig::slot_type const &);
+       /// disconnect all slots connected to the boost signal fileChanged_ or to
+       /// the qt signal fileChanged()
+       void disconnect();
+diff --git a/src/support/ForkedCalls.cpp b/src/support/ForkedCalls.cpp
+index f81c1d2..93be6a4 100644
+--- a/src/support/ForkedCalls.cpp
++++ b/src/support/ForkedCalls.cpp
+@@ -58,7 +58,7 @@ namespace {
+ //
+ /////////////////////////////////////////////////////////////////////
+-class Murder {
++class Murder : public boost::signals2::trackable {
+ public:
+       //
+       static void killItDead(int secs, pid_t pid)
+@@ -83,8 +83,7 @@ private:
+       Murder(int secs, pid_t pid)
+               : timeout_(1000*secs, Timeout::ONETIME), pid_(pid)
+       {
+-              // Connection is closed with this.
+-              timeout_.timeout.connect([this](){ kill(); });
++              timeout_.timeout.connect(lyx::bind(&Murder::kill, this));
+               timeout_.start();
+       }
+@@ -278,7 +277,7 @@ ForkedCall::ForkedCall(string const & path, string const & lpath)
+ int ForkedCall::startScript(Starttype wait, string const & what)
+ {
+       if (wait != Wait) {
+-              retval_ = startScript(what, sigPtr());
++              retval_ = startScript(what, SignalTypePtr());
+               return retval_;
+       }
+@@ -288,7 +287,7 @@ int ForkedCall::startScript(Starttype wait, string const & what)
+ }
+-int ForkedCall::startScript(string const & what, sigPtr signal)
++int ForkedCall::startScript(string const & what, SignalTypePtr signal)
+ {
+       command_ = commandPrep(trim(what));
+       signal_  = signal;
+@@ -436,13 +435,13 @@ int ForkedCall::generateChild()
+ namespace ForkedCallQueue {
+ /// A process in the queue
+-typedef pair<string, ForkedCall::sigPtr> Process;
++typedef pair<string, ForkedCall::SignalTypePtr> Process;
+ /** Add a process to the queue. Processes are forked sequentially
+  *  only one is running at a time.
+  *  Connect to the returned signal and you'll be informed when
+  *  the process has ended.
+  */
+-ForkedCall::sigPtr add(string const & process);
++ForkedCall::SignalTypePtr add(string const & process);
+ /// in-progress queue
+ static queue<Process> callQueue_;
+@@ -457,10 +456,10 @@ void stopCaller();
+ ///
+ void callback(pid_t, int);
+-ForkedCall::sigPtr add(string const & process)
++ForkedCall::SignalTypePtr add(string const & process)
+ {
+-      ForkedCall::sigPtr ptr;
+-      ptr.reset(new ForkedCall::sig);
++      ForkedCall::SignalTypePtr ptr;
++      ptr.reset(new ForkedCall::SignalType);
+       callQueue_.push(Process(process, ptr));
+       if (!running_)
+               startCaller();
+diff --git a/src/support/ForkedCalls.h b/src/support/ForkedCalls.h
+index 8a4bf1d..eececc0 100644
+--- a/src/support/ForkedCalls.h
++++ b/src/support/ForkedCalls.h
+@@ -14,8 +14,8 @@
+ #ifndef FORKEDCALLS_H
+ #define FORKEDCALLS_H
+-#include "support/signals.h"
+ #include "support/strfwd.h"
++#include <boost/signals2.hpp>
+ #ifdef HAVE_SYS_TYPES_H
+ # include <sys/types.h>
+@@ -44,7 +44,7 @@ public:
+       ///
+       virtual std::shared_ptr<ForkedProcess> clone() const = 0;
+-      /** A Signal signal can be emitted once the forked process
++      /** A SignalType signal can be emitted once the forked process
+        *  has finished. It passes:
+        *  the PID of the child and;
+        *  the return value from the child.
+@@ -53,8 +53,7 @@ public:
+        *  we can return easily to C++ methods, rather than just globally
+        *  accessible functions.
+        */
+-      typedef signals2::signal<void(pid_t, int)> sig;
+-      typedef sig::slot_type slot;
++      typedef boost::signals2::signal<void(pid_t, int)> SignalType;
+       /** The signal is connected in the calling routine to the desired
+        *  slot. We pass a shared_ptr rather than a reference to the signal
+@@ -62,10 +61,9 @@ public:
+        *  class (and hence the signal) to be destructed before the forked
+        *  call is complete.
+        *
+-       *  Use Slot::track or Signal::scoped_connection to ensure that the
+-       *  connection is closed before the slot expires.
++       *  It doesn't matter if the slot disappears, SigC takes care of that.
+        */
+-      typedef std::shared_ptr<sig> sigPtr;
++      typedef std::shared_ptr<SignalType> SignalTypePtr;
+       /** Invoking the following methods makes sense only if the command
+        *  is running asynchronously!
+@@ -116,7 +114,7 @@ protected:
+       pid_t fork();
+       /// Callback function
+-      sigPtr signal_;
++      SignalTypePtr signal_;
+       /// identifying command (for display in the GUI perhaps).
+       std::string command_;
+@@ -138,7 +136,7 @@ private:
+ };
+-/**
++/** 
+  * An instance of class ForkedCall represents a single child process.
+  *
+  * Class ForkedCall uses fork() and execvp() to lauch the child process.
+@@ -177,7 +175,7 @@ public:
+       int startScript(Starttype, std::string const & what);
+       ///
+-      int startScript(std::string const & what, sigPtr ptr);
++      int startScript(std::string const & what, SignalTypePtr);
+ private:
+       ///
+@@ -197,7 +195,7 @@ private:
+ namespace ForkedCallQueue {
+-ForkedCall::sigPtr add(std::string const & process);
++ForkedCall::SignalTypePtr add(std::string const & process);
+ /// Query whether the queue is running a forked process now.
+ bool running();
+diff --git a/src/support/Makefile.am b/src/support/Makefile.am
+index d3c902c..9865d6f 100644
+--- a/src/support/Makefile.am
++++ b/src/support/Makefile.am
+@@ -93,7 +93,6 @@ liblyxsupport_a_SOURCES = \
+       qstring_helpers.h \
+       regex.h \
+       RefChanger.h \
+-      signals.h \
+       socktools.cpp \
+       socktools.h \
+       strfwd.h \
+diff --git a/src/support/Timeout.h b/src/support/Timeout.h
+index eef78db..042ed45 100644
+--- a/src/support/Timeout.h
++++ b/src/support/Timeout.h
+@@ -12,7 +12,7 @@
+ #ifndef TIMEOUT_H
+ #define TIMEOUT_H
+-#include "support/signals.h"
++#include <boost/signals2.hpp>
+ namespace lyx {
+@@ -40,7 +40,7 @@ public:
+       /// restart the timer
+       void restart();
+       /// signal emitted on timer expiry
+-      signals2::signal<void()> timeout;
++      boost::signals2::signal<void()> timeout;
+       /// emit the signal
+       void emit();
+       /// set the timer type
+diff --git a/src/support/signals.h b/src/support/signals.h
+deleted file mode 100644
+index 7d4d116..0000000
+--- a/src/support/signals.h
++++ /dev/null
+@@ -1,49 +0,0 @@
+-// -*- C++ -*-
+-/**
+- * \file signals.h
+- * This file is part of LyX, the document processor.
+- * Licence details can be found in the file COPYING.
+- *
+- * \author Guillaume Munch
+- *
+- * Full author contact details are available in file CREDITS.
+- */
+-
+-#ifndef LYX_SIGNALS_H
+-#define LYX_SIGNALS_H
+-
+-#include "boost/signals2.hpp"
+-
+-#include <memory>
+-
+-namespace lyx {
+-
+-namespace signals2 = ::boost::signals2;
+-
+-namespace support {
+-
+-/// A small utility to use with signals2::slot_type::track_foreign when the
+-/// parent object is not handled by a shared_ptr, or to track the lifetime of an
+-/// object. Using Trackable to track lifetimes is less thread-safe than tracking
+-/// their parents directly with a shared_ptr as recommended by signals2, but it
+-/// makes it easier for transitioning old code. (Essentially because Trackable
+-/// will not prevent the deletion of the parent by a concurrent thread.)
+-class Trackable {
+-public:
+-      Trackable() : p_(std::make_shared<int>(0)) {}
+-      Trackable(Trackable const &) : Trackable() {}
+-      Trackable(Trackable &&) : Trackable() {}
+-      Trackable & operator=(Trackable const &) { return *this; }
+-      Trackable & operator=(Trackable &&) { return *this; }
+-      // This weak pointer lets you know if the parent object has been destroyed
+-      std::weak_ptr<void> p() const { return p_; }
+-private:
+-      std::shared_ptr<void> const p_;
+-};
+-
+-} // namespace support
+-
+-} // namespace lyx
+-
+-
+-#endif
+
+commit c6b1ee490c9467230ba7033bd15feb4753832c4b
+Author: Pavel Sanda <psanda@ucsd.edu>
+Date:   Thu Nov 16 09:38:27 2017 -0800
+
+    one forgotten line in rejects
+
+diff --git a/src/Buffer.cpp b/src/Buffer.cpp
+index 48391f9..1945b71 100644
+--- a/src/Buffer.cpp
++++ b/src/Buffer.cpp
+@@ -5349,7 +5349,7 @@ void Buffer::Impl::refreshFileMonitor()
+ }
+-void Buffer::Impl::fileExternallyModified(bool const exists)
++void Buffer::Impl::fileExternallyModified(bool modified)
+ {
+       if (modified) 
+               lyx_clean = bak_clean = false;