emacs-devel
[Top][All Lists]
Advanced

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

Re: unwind-protect not cleaning up?


From: Jambunathan K
Subject: Re: unwind-protect not cleaning up?
Date: Sun, 01 Jul 2012 23:17:52 +0530
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.1 (windows-nt)

Eli Zaretskii <address@hidden> writes:

>> From: Jambunathan K <address@hidden>
>> Date: Sat, 30 Jun 2012 11:01:21 +0530
>> Cc: address@hidden
>> 
>> Nothing in the manual suggests that some sort of user-intervention
>> is required for recovery.
>
> Because no intervention is needed, in general.  It's just that you
> tried to trigger the stack unwinding with something that signals an
> error and enters the debugger.  Change your example to this:
>
>   (let ((buffer (get-buffer-create "YOU CANNOT KILL ME")))
>     (with-current-buffer buffer
>       (let ((eval-expression-debug-on-error nil)
>           (debug-on-signal nil))
>       (unwind-protect
>         (/ 1 0)
>       (kill-buffer buffer)))))
>
> and you will get what you expected without any user intervention.

`eval-expression-debug-on-error' and `debug-on-signal' (as used above)
is really too much of an information for a developer who is not working
in Emacs core.  Though the above information is useful, it is unlikely
that a Random Joe developer will actually use it.  So these need not be
documented.

>> May be I should be looking at someother API that "guarantees" cleanup
>> very much like unwind-protect, without the 'c' part.
>> 
>> I can use (condition-case VAR BODYFORM &rest HANDLERS) with the cleanup
>> happening both in BODYFORM and also in (error ) HANDLER.  I felt that
>> unwind-protect construct is more elegant.  Any suggestions...
>
> The popular use for unwind-protect is when the user could C-g inside
> the protected form.  For errors such as division by zero,
> condition-case is indeed better, as you can run some code when the
> error is thrown.

>> Btw, if unwind-protect is behaving the right way, manpage needs an
>> update...
>
> We don't have manpages in Emacs.  Did you mean the manual?  If so,
> what would you suggest to add/update there, in view of the above?

Here is my recommendation for "(elisp) Cleanups".  Re-word it for
correctness or trim it for brevity.

If a (long-running) command allocates resources - processes or buffers -
for it's own work and it needs to be aborted mid-way (remember it is
long-running and the user might lose patience), then one should use an
unwind-protect with cleanup handlers.  This way when the user aborts the
command with C-g the command is stopped cleanly.

A command could become long-running against developer's wishes.  So
 insert a cross-reference to (info "(elisp) Infinite Loops").

We can make the example simpler, with an actual infinite loop as below.

(let ((buffer (get-buffer-create " *temp*")))
  (with-current-buffer buffer
    (unwind-protect
        (while t (ignore)) ;; hog the cpu
      (kill-buffer buffer))))

If `debug-on-quit' is nil, then on C-g cleanup forms are executed.

[ADDITIONAL NOTE]
However, if `debug-on-quit' is t, continuing from the debugger with 'c'
will resume the protected form (and cleanup form will not be executed?)

I will also split the "Cleanups" in to two nodes.  For want of better
names, let me call it "Cleanup on quit" and "Cleanup on error".
`unwind-protect' will go in the first node and `condition-case' in the
second node.  (Manual goes an extra length to clarify that quit and
error are actually two different things.)


[CONTEXT SWITCH]
I also tried comparing `condition-case' with `unwind-protect'.

     (condition-case err
         (error "Forced error")
       ((debug error) ;; ASSIGNMENT TO THE READER: add `quit' to this
                      ;; list and see the behaviour on C-g with various
                      ;; values of `debug-on-quit'.  Particularly note
                      ;; whether or not the handler is called.
        (message "Released resources")))

With `debug' added to the list and `debug-on-error' set to `t', a
developer can examine the stacktrace and also trigger the cleanup with a
`c'.  In other words, the cleanup happens irrespective of the value of
`debug-on-error'.  (Compare this behaviour with C-g and `debug-on-quit',
search for ADDITIONAL NOTE above)

-- 



reply via email to

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