unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Atomic file replacement in Emacs
@ 2020-10-21 16:27 Zhu Zihao
  2020-10-21 19:49 ` Andreas Schwab
  0 siblings, 1 reply; 7+ messages in thread
From: Zhu Zihao @ 2020-10-21 16:27 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1572 bytes --]

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))))



[-- Attachment #2: Type: text/plain, Size: 613 bytes --]

-----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-----

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2020-10-22  6:35 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-21 16:27 Atomic file replacement in Emacs Zhu Zihao
2020-10-21 19:49 ` Andreas Schwab
2020-10-21 20:32   ` Stefan Monnier
2020-10-21 20:38     ` Andreas Schwab
2020-10-21 20:46       ` Stefan Monnier
2020-10-21 23:25   ` Zhu Zihao
2020-10-22  6:35   ` Zhu Zihao

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).