> If you want to raise an exception from a
> kill-emacs-hook (assuming that you want the unwind-protect forms to do
> something), you can do that from kill-emacs-hook, no?
No, I tried. There is a "shield" at C level that prevents me from passing an
exception from a `kill-emacs-hook' to the "main" code:
$ emacs --batch \
--eval "(add-hook 'kill-emacs-hook (lambda () (signal 'unwind-the-stack nil)))" \
--eval "(unwind-protect (while t) (message \"GOING DOWN\"))"
^CError in kill-emacs-hook ((closure (t) nil (signal 'unwind-the-stack nil))): (unwind-the-stack)
As you see, the exception doesn't succeed in making `unwind-protect'
clause to run.
> And if you had a say in handling SIGINT, what would you do in the
> handler that you cannot do in kill-emacs-hook?
It's not the point of doing something special, it's rather the point of
doing _normal_ cleanup that I expected to do otherwise. Let's say my
program does 20 different, sometimes nested and sometimes not
allocations of external resources that I need to free/close somehow.
If `unwind-protect' was guaranteed to run (even in response to C-c)
I could just do
(unwind-protect
(do-something-with-resource-N)
(free) (resource-N) (code))
twenty times. However, as it stands it looks that I have to do
(let ((free-resource-N (lambda () (free) (resource-N) (code))))
(add-hook 'kill-emacs-hook free-resource-N)
(unwind-protect
(do-something-with-resource-N)
(funcall free-resource-N))
(remove-hook 'kill-emacs-hook free-resource-N))
every time.
Additionally, this won't work if I don't control the code that
allocates/frees the resource, i.e. if it happens to be inside some
external package.
> Also, you mention batch mode, but is it relevant?
No, not really. It's just that in batch mode I was expecting to be in full
control of Emacs "command loop" because I don't share Emacs with any
other code (or at most that code can be seen as a "library" for my
program). In interactive mode it's basically the same.
Paul