Prevent false positives in external modifications

When the Buffer is notified to be externally modified, check that the
file contents have changed using the checksum.

Document the shortcoming of FileMonitorBlocker.

Fixes #10642.
This commit is contained in:
Guillaume MM 2017-05-13 01:00:30 +02:00
parent db58111360
commit 2058faaa3b
2 changed files with 21 additions and 6 deletions

View File

@ -386,7 +386,7 @@ public:
void fileExternallyModified(bool modified) const; void fileExternallyModified(bool modified) const;
/// Block notifications of external modifications /// Block notifications of external modifications
FileMonitorBlocker blockFileMonitor() { return file_monitor_->block(10); } FileMonitorBlocker blockFileMonitor() { return file_monitor_->block(); }
private: private:
/// So we can force access via the accessors. /// So we can force access via the accessors.
@ -5341,8 +5341,16 @@ void Buffer::Impl::refreshFileMonitor()
void Buffer::Impl::fileExternallyModified(bool modified) const void Buffer::Impl::fileExternallyModified(bool modified) const
{ {
if (modified) 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;
}
lyx_clean = bak_clean = false; lyx_clean = bak_clean = false;
}
externally_modified_ = modified; externally_modified_ = modified;
if (wa_) if (wa_)
wa_->updateTitles(); wa_->updateTitles();

View File

@ -167,11 +167,18 @@ public:
/// absolute path being tracked /// absolute path being tracked
std::string const & filename() { return monitor_->filename(); } std::string const & filename() { return monitor_->filename(); }
/// Creates a guard that blocks notifications. Copyable. Notifications from /// Creates a guard that blocks notifications. Copyable. Notifications from
/// this monitor are blocked as long as there are copies around. /// 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 /// \param delay is the amount waited in ms after expiration of the guard
/// before reconnecting. This delay thing is to deal with asynchronous /// before reconnecting. It can be used to slow down incoming events
/// notifications in a not so elegant fashion. But it can also be used to /// accordingly. A value of 0 is still made asynchronous, because of the
/// slow down incoming events. /// 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>.
FileMonitorBlocker block(int delay = 0); FileMonitorBlocker block(int delay = 0);
/// Make sure the good file is being monitored, after e.g. a move or a /// 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 /// deletion. See <https://bugreports.qt.io/browse/QTBUG-46483>. This is