emacs-devel
[Top][All Lists]
Advanced

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

Atomic file replacement in Emacs


From: Zhu Zihao
Subject: Atomic file replacement in Emacs
Date: Thu, 22 Oct 2020 00:27:50 +0800
User-agent: mu4e 1.4.13; emacs 27.1

It's a very common case to persist data structure using `pp` or `prin1`.
However, the core function of saving a buffer, `write-region` is not
atomic. If your data structure is very very large, and something
happened(e.g. you sent SIGKILL to Emacs, or the power of your computer
was cut) during saving, it will probably result in a broken file.

File system should provide some atomic operation to deal with these
conditions. There's a "trick" to do this job -- write to a temp file in
same directory, then use libc's rename to override origin file. Because
rename is atomic in same mount point. Our file can be replaced
atomically.

I'd like to suggest a implementation draft here. If you think this is good, I
can help make a patch to add it to files.el

~~~

(defmacro with-atomic-file-replacement (file &rest body)
  "Open FILE in a temp buffer and evaluate BODY in it, replace the FILE with 
the buffer content atomically"
  (declare (debug t) (indent 1))
  `(call-with-atomic-file-replacement ,file (lambda () ,@body)))

(defun call-with-atomic-file-replacement (file func)
  ;; The atomic of rename in libc was guaranteed by POSIX
  ;; standard, it will fail if we rename file between two mount point. So create
  ;; temp file in the same dir  of FILE.
  (let* ((full (expand-file-name file))
         (dir (file-name-directory full))
         (tmpfile (make-temp-file dir)))
    (with-temp-buffer
      (setq buffer-file-name tmpfile)
      (insert-file-contents-literally full)
      (funcall func)
      (basic-save-buffer)
      (rename-file tmpfile full t))))


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256


- --
Retrieve my public GPG key from: https://meta.sr.ht/~citreu.pgp
Zihao
-----BEGIN PGP SIGNATURE-----

iQEzBAEBCAAdFiEE7NCVzXX6efyusptG1SOVn+xGFqYFAl+QYYYACgkQ1SOVn+xG
FqbKoAf7BjNawuGgbwYgZNIE4j2WT6x2Zbi2E3RuoPfqmww/GXgzHDjc+TlctH0T
+hJVDb7+SrvhaOv4rjYu8gUIDZK67lpZD/axtVJfxV1+yqKA5MtVZdgw6xsPir4y
+40QkcgWUcD6EtSaqR85vjj80st8HKouUEn16f6hB2Dh9kptd4DfvVJYKV+7ndP2
yjKDseIgmNNiHny3jKw1HON+h9O9+10YLysFXieoKq3paTHmIHChoNhb898FPKEd
f/P8hTiV3ZAvLgLU6pLzN46MrYoUR8m72o4ZwzFn5gn/B/Bke6oRKEZLs1vHavBw
2quRGNG+SdKUDpDO/SvXmbWe635uPA==
=BoM1
-----END PGP SIGNATURE-----

reply via email to

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