Subject: bug#75209: 30.0.93; Emacs reader failed to read data in "/home/nlj/.cache/org-persist/gc-lock.eld"

From: Eli Zaretskii <[email-masked]>
Date: Thu, 02 Jan 2025 20:48:42 +0200

> From: Ihor Radchenko <[email-masked]>
> Cc: [email-masked], [email-masked]
> Date: Thu, 02 Jan 2025 17:28:02 +0000
> 
> Eli Zaretskii <[email-masked]> writes:
> 
> > Can you tell more about the purpose and use of this file?  What is
> > written to it, and how is it supposed to be used after being written?
> > And what bad things happen when the Lisp readers errors out because it
> > is unable to read the data for some reason?
> 
> Let me then describe briefly what org-persist does.
> 
> In the nutshell, it is cache manager.
> The main cache data consists of:
> 1. index describing everything stored in the cache and its expiry
>    settings
> 2. cache data stored in individual files. Each file in the cache is
>    mentioned in the index file
> 
> >From time to time (before quitting Emacs), org-persist needs to do some
> "garbage collection" and remove cache files that are expired or
> unreferenced from index to avoid cache growing infinitely.
> 
> The GC process works well, and helps keeping the cache directory
> clean. However, there are problems when multiple Emacs processes are
> running simultaneously.
> 
> Consider Emacs A loading cache index into memory and doing nothing.
> Then, Emacs B also loads the cache index, but adds data to the cache.
> If Emacs A is closed while Emacs B is running (and Emacs B not yet
> updating cache index on disk), it also performs garbage
> collection. However, Emacs A has no knowledge about cache data written
> by Emacs B and may "garabge collect" this data. We do not want that.

Thanks.  I think I still don't have a clear idea of the usage of these
caches.  Are the caches supposed to be common to all Emacs sessions?
E.g., when a cache changes by one session, are other sessions supposed
to know about the change?  If the cache is for a single session, then
why are several session allowed to write to the cache simultaneously?
And if the cache is common to all sessions, then perhaps reading the
index before writing it should avoid several sessions step on each
other's toes?

> "gc-lock.eld" keeps track of the running Emacs processes - every Emacs
> process regularly write to "gc-lock.eld", putting a record in the form
> of (before-init-time . <last known time that Emacs is running>). If
> there are no known recently running Emacs processes (apart from
> current), garbage collection process is suppressed to avoid removing
> cache data from other Emacsen.

One way of rewriting a file atomically is to write the stuff to a
temporary file, then rename it to the target name.  If Org doesn't
already do that, maybe you should try doing that (together with
reading the file before updating it)?