GNU Info

Info Node: (elisp)Cleanups

(elisp)Cleanups


Prev: Errors Up: Nonlocal Exits
Enter node , (file) or (file)node

Cleaning Up from Nonlocal Exits
-------------------------------

   The `unwind-protect' construct is essential whenever you temporarily
put a data structure in an inconsistent state; it permits you to make
the data consistent again in the event of an error or throw.

 - Special Form: unwind-protect body cleanup-forms...
     `unwind-protect' executes the BODY with a guarantee that the
     CLEANUP-FORMS will be evaluated if control leaves BODY, no matter
     how that happens.  The BODY may complete normally, or execute a
     `throw' out of the `unwind-protect', or cause an error; in all
     cases, the CLEANUP-FORMS will be evaluated.

     If the BODY forms finish normally, `unwind-protect' returns the
     value of the last BODY form, after it evaluates the CLEANUP-FORMS.
     If the BODY forms do not finish, `unwind-protect' does not return
     any value in the normal sense.

     Only the BODY is protected by the `unwind-protect'.  If any of the
     CLEANUP-FORMS themselves exits nonlocally (via a `throw' or an
     error), `unwind-protect' is _not_ guaranteed to evaluate the rest
     of them.  If the failure of one of the CLEANUP-FORMS has the
     potential to cause trouble, then protect it with another
     `unwind-protect' around that form.

     The number of currently active `unwind-protect' forms counts,
     together with the number of local variable bindings, against the
     limit `max-specpdl-size' (Note: Local Variables).

   For example, here we make an invisible buffer for temporary use, and
make sure to kill it before finishing:

     (save-excursion
       (let ((buffer (get-buffer-create " *temp*")))
         (set-buffer buffer)
         (unwind-protect
             BODY
           (kill-buffer buffer))))

You might think that we could just as well write `(kill-buffer
(current-buffer))' and dispense with the variable `buffer'.  However,
the way shown above is safer, if BODY happens to get an error after
switching to a different buffer!  (Alternatively, you could write
another `save-excursion' around the body, to ensure that the temporary
buffer becomes current again in time to kill it.)

   Emacs includes a standard macro called `with-temp-buffer' which
expands into more or less the code shown above (Note: Current Buffer).
Several of the macros defined in this manual use `unwind-protect' in
this way.

   Here is an actual example derived from an FTP package.  It creates a
process (Note: Processes) to try to establish a connection to a remote
machine.  As the function `ftp-login' is highly susceptible to numerous
problems that the writer of the function cannot anticipate, it is
protected with a form that guarantees deletion of the process in the
event of failure.  Otherwise, Emacs might fill up with useless
subprocesses.

     (let ((win nil))
       (unwind-protect
           (progn
             (setq process (ftp-setup-buffer host file))
             (if (setq win (ftp-login process host user password))
                 (message "Logged in")
               (error "Ftp login failed")))
         (or win (and process (delete-process process)))))

   This example has a small bug: if the user types `C-g' to quit, and
the quit happens immediately after the function `ftp-setup-buffer'
returns but before the variable `process' is set, the process will not
be killed.  There is no easy way to fix this bug, but at least it is
very unlikely.


automatically generated by info2www version 1.2.2.9