bug-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#46397: 27.1; Cannot delete buffer pointing to a file in a path that


From: Matt Armstrong
Subject: bug#46397: 27.1; Cannot delete buffer pointing to a file in a path that includes a file
Date: Fri, 12 Feb 2021 17:15:42 -0800

Eli Zaretskii <eliz@gnu.org> writes:

>> Cc: 46397@debbugs.gnu.org, craven@gmx.net
>> From: Paul Eggert <eggert@cs.ucla.edu>
>> Date: Thu, 11 Feb 2021 18:20:44 -0800
>> 
>> On 2/11/21 2:14 PM, Matt Armstrong wrote:
>> 
>> > The issue isn't confined to exiting Emacs. It appears that once in a
>> > "tricky situation where the file can't be unlocked for whatever reason"
>> > Emacs will refuse to kill the buffer because unlock_file() signals an
>> > error.
>> 
>> kill-buffer already asks the user something like "Buffer XXX modified; 
>> kill anyway? (yes or no)" when killing a buffer that's been changed 
>> without being saved. Perhaps it should also ask "File XXX cannot be 
>> unlocked; kill buffer anyway? (yes or no)" if the file can't be unlocked.
>> 
>> > Note that shut_down_emacs() calls Fdo_auto_save() just before
>> > unlock_all_files() and that call succeeds. Fdo_auto_save() also calls
>> > report_file_errno, throwing an errno 13 (Permission denied), but that
>> > recovers and continues.
>> 
>> Presumably shut_down_emacs should recover and continue if 
>> unlock_all_files fails when it directly calls unlock_all_files.
>
> That all is true, but I think we should provide for recovery in a way
> that will work with _any_ command that calls unlock_file or
> unlock_all_files.  Not just these two instances.  See my other message
> about this.

Eli, I looked a bit at finding a general solution.

One obvious issue is my inexperience in the code base. The locking logic
all seems handled in C code, and I'm not yet very familiar with Emacs'
particularities. Most of my multi-decade long career has been in lower
level C++ code, so it is semi-familiar, but I haven't yet internalized
how to think about problems in the Emacs lispy-way. I keep grasping for
expressions of OO ideas that just aren't there, or at least aren't clear
to me. :)

One issue is that 'unlock_file' has about 10 callers (though over half
are from write-region).

I'm not sure how functions like 'write_region',
'restore-buffer-modified-p' and 'replace-buffer-contents' should be
handling lock and unlock failures.

I think save-buffers-kill-terminal should be modified to leave the
buffers in a state that won't trigger un-locking much later (after it is
too late to do proper UI interactions). If a user opts to not save a
buffer, then the unlock could happen immediately (and possibly surface
an error of its own). Sound good?

One problem with the above: currently buffers do not track whether Emacs
thinks they hold the lock. Normally I'd think about adding a "user chose
to ignore unlock errors" flag at that spot, but it doesn't exist.

Instead, code attempts to re-verify lock state from the file system at
every operation. Not even setting `create-lockfiles' to nil is enough to
prevent Emacs from attempting to delete them. Some mechanism to record
the user's desire to bypass lock file errors is needed.

There is also the case where 'kill_emacs' is called from a signal, which
seems to proceed directly to shutdown without prompting the user to save
buffers. For this flow, I think the only option is to "swallow" the
errors while unlocking files. The Emacs manually even allows or this
possibility (mentioning "if Emacs crashes..."). Sound good?

You have suggested showing a prompt. What question would it ask? I am
having trouble imagining ways of making the situation clear to the user.
There are also many situations:

 - unable to determine if Emacs has the lock
 - unable to acquire the lock
 - unable to release the lock

None of these are questions. What do we expect the user to actually
understand and answer to from these prompts? Or, is issuing a message
sufficient? A message would certainly simplify things.





reply via email to

[Prev in Thread] Current Thread [Next in Thread]