Skip to content

looking-glass: replace pyinotify with Gio.FileMonitor#13898

Open
Fantu wants to merge 1 commit into
linuxmint:masterfrom
Fantu:looking-glass-gio-file-monitor
Open

looking-glass: replace pyinotify with Gio.FileMonitor#13898
Fantu wants to merge 1 commit into
linuxmint:masterfrom
Fantu:looking-glass-gio-file-monitor

Conversation

@Fantu

@Fantu Fantu commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

cinnamon-looking-glass.py is the only thing in Cinnamon still using pyinotify, for the file watcher tabs ("Actions → Add File Watcher") that tail a log file.

pyinotify is a problem now:

  • upstream is dead — last release 0.9.6 in 2015, no commits since, see seb-m/pyinotify;
  • it does import asyncore at module level, and asyncore was removed from the Python standard library in 3.12. It still imports today only because distributions ship a third-party backport of that module as an extra dependency (Debian added python3-pyasyncore to python3-pyinotify for exactly this reason);
  • distributions have started filing bugs against every reverse dependency to get rid of it — for Cinnamon this is Debian #1075948, part of #1004387.

Gio.FileMonitor does the same job and comes from python3-gi, which Cinnamon already depends on, so this drops a dependency rather than trading it for another one — no new build or runtime requirement, and Gio was already imported in this file.

There is a second, smaller benefit. pyinotify.ThreadedNotifier runs its own thread and called get_updates() from there, so the log view — and therefore Gtk.TextBuffer.set_text() in update() — was being driven from outside the main loop. Gio.FileMonitor emits changed on the thread-default main context, so everything now stays on the main loop.

What changed

  • FileWatchHandler (the pyinotify.ProcessEvent subclass) is gone; its four process_IN_* methods all did the same thing and collapse into a single on_file_changed() callback.
  • FileWatcherView monitors the file with Gio.File.new_for_path(filename).monitor_file() and cancels the monitor on destroy, instead of starting/stopping a ThreadedNotifier.
  • pyinotify dropped from debian/control and from the pylint extension-pkg-whitelist.

The IN_CLOSE_WRITE | IN_CREATE | IN_DELETE | IN_MODIFY mask maps onto the default GFileMonitor events (changed, changes-done-hint, created, deleted), all of which just trigger a refresh. The existing 500 ms rate limiting in get_updates() is untouched and also absorbs the changed + changes-done-hint pair that GFileMonitor emits for a single write.

Testing

Tested on a Debian sid VM with Cinnamon 6.6.8, driving FileWatcherView directly on the running session: appending to the watched file refreshes the text buffer exactly as before, and the monitor is cancelled when the view is destroyed. Running the same test against the unmodified file shows the thread count going from 1 to 2 (the ThreadedNotifier), while with Gio.FileMonitor it stays at 1.

Also checked manually from the UI: Looking Glass → Actions → Add File Watcher on a log file, the tab updates and auto-scrolls as before.

pyinotify has been unmaintained upstream since 2015 and it imports
asyncore, which was removed from the Python standard library in 3.12; it
currently keeps working only because distributions pull in a third-party
backport of that module.

Gio.FileMonitor provides the same functionality through python3-gi,
which Cinnamon already depends on, so the log file watcher in Looking
Glass loses a dependency instead of trading it for another one.

It also fixes a latent thread-safety problem: pyinotify's
ThreadedNotifier dispatched the callbacks from its own thread, so the
log view (and therefore Gtk.TextBuffer) was refreshed from outside the
main loop. Gio.FileMonitor emits "changed" on the thread-default main
context. The existing 500 ms rate limiting is unchanged and also absorbs
the changed/changes-done-hint pair GFileMonitor emits for a single
write.

Also drop python3-pyinotify from debian/control and pyinotify from the
pylint extension whitelist, as nothing else uses it.

Assisted-by: Claude Code:claude-opus-4-8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant