GDB (API)
/home/stan/gdb/src/gdb/cleanups.c
Go to the documentation of this file.
00001 /* Cleanup routines for GDB, the GNU debugger.
00002 
00003    Copyright (C) 1986-2013 Free Software Foundation, Inc.
00004 
00005    This file is part of GDB.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 3 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00019 
00020 #include "defs.h"
00021 #include "gdb_assert.h"
00022 
00023 /* The cleanup list records things that have to be undone
00024    if an error happens (descriptors to be closed, memory to be freed, etc.)
00025    Each link in the chain records a function to call and an
00026    argument to give it.
00027 
00028    Use make_cleanup to add an element to the cleanup chain.
00029    Use do_cleanups to do all cleanup actions back to a given
00030    point in the chain.  Use discard_cleanups to remove cleanups
00031    from the chain back to a given point, not doing them.
00032 
00033    If the argument is pointer to allocated memory, then you need
00034    to additionally set the 'free_arg' member to a function that will
00035    free that memory.  This function will be called both when the cleanup
00036    is executed and when it's discarded.  */
00037 
00038 struct cleanup
00039 {
00040   struct cleanup *next;
00041   void (*function) (void *);
00042   void (*free_arg) (void *);
00043   void *arg;
00044 };
00045 
00046 /* Used to mark the end of a cleanup chain.
00047    The value is chosen so that it:
00048    - is non-NULL so that make_cleanup never returns NULL,
00049    - causes a segv if dereferenced
00050      [though this won't catch errors that a value of, say,
00051      ((struct cleanup *) -1) will]
00052    - displays as something useful when printed in gdb.
00053    This is const for a bit of extra robustness.
00054    It is initialized to coax gcc into putting it into .rodata.
00055    All fields are initialized to survive -Wextra.  */
00056 static const struct cleanup sentinel_cleanup = { 0, 0, 0, 0 };
00057 
00058 /* Handy macro to use when referring to sentinel_cleanup.  */
00059 #define SENTINEL_CLEANUP ((struct cleanup *) &sentinel_cleanup)
00060 
00061 /* Chain of cleanup actions established with make_cleanup,
00062    to be executed if an error happens.  */
00063 static struct cleanup *cleanup_chain = SENTINEL_CLEANUP;
00064 
00065 /* Chain of cleanup actions established with make_final_cleanup,
00066    to be executed when gdb exits.  */
00067 static struct cleanup *final_cleanup_chain = SENTINEL_CLEANUP;
00068 
00069 /* Main worker routine to create a cleanup.
00070    PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
00071    FUNCTION is the function to call to perform the cleanup.
00072    ARG is passed to FUNCTION when called.
00073    FREE_ARG, if non-NULL, is called after the cleanup is performed.
00074 
00075    The result is a pointer to the previous chain pointer
00076    to be passed later to do_cleanups or discard_cleanups.  */
00077 
00078 static struct cleanup *
00079 make_my_cleanup2 (struct cleanup **pmy_chain, make_cleanup_ftype *function,
00080                   void *arg,  void (*free_arg) (void *))
00081 {
00082   struct cleanup *new
00083     = (struct cleanup *) xmalloc (sizeof (struct cleanup));
00084   struct cleanup *old_chain = *pmy_chain;
00085 
00086   new->next = *pmy_chain;
00087   new->function = function;
00088   new->free_arg = free_arg;
00089   new->arg = arg;
00090   *pmy_chain = new;
00091 
00092   gdb_assert (old_chain != NULL);
00093   return old_chain;
00094 }
00095 
00096 /* Worker routine to create a cleanup without a destructor.
00097    PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
00098    FUNCTION is the function to call to perform the cleanup.
00099    ARG is passed to FUNCTION when called.
00100 
00101    The result is a pointer to the previous chain pointer
00102    to be passed later to do_cleanups or discard_cleanups.  */
00103 
00104 static struct cleanup *
00105 make_my_cleanup (struct cleanup **pmy_chain, make_cleanup_ftype *function,
00106                  void *arg)
00107 {
00108   return make_my_cleanup2 (pmy_chain, function, arg, NULL);
00109 }
00110 
00111 /* Add a new cleanup to the cleanup_chain,
00112    and return the previous chain pointer
00113    to be passed later to do_cleanups or discard_cleanups.
00114    Args are FUNCTION to clean up with, and ARG to pass to it.  */
00115 
00116 struct cleanup *
00117 make_cleanup (make_cleanup_ftype *function, void *arg)
00118 {
00119   return make_my_cleanup (&cleanup_chain, function, arg);
00120 }
00121 
00122 /* Same as make_cleanup except also includes TDOR, a destructor to free ARG.
00123    DTOR is invoked when the cleanup is performed or when it is discarded.  */
00124 
00125 struct cleanup *
00126 make_cleanup_dtor (make_cleanup_ftype *function, void *arg,
00127                    void (*dtor) (void *))
00128 {
00129   return make_my_cleanup2 (&cleanup_chain,
00130                            function, arg, dtor);
00131 }
00132 
00133 /* Same as make_cleanup except the cleanup is added to final_cleanup_chain.  */
00134 
00135 struct cleanup *
00136 make_final_cleanup (make_cleanup_ftype *function, void *arg)
00137 {
00138   return make_my_cleanup (&final_cleanup_chain, function, arg);
00139 }
00140 
00141 /* Worker routine to perform cleanups.
00142    PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
00143    OLD_CHAIN is the result of a "make" cleanup routine.
00144    Cleanups are performed until we get back to the old end of the chain.  */
00145 
00146 static void
00147 do_my_cleanups (struct cleanup **pmy_chain,
00148                 struct cleanup *old_chain)
00149 {
00150   struct cleanup *ptr;
00151 
00152   while ((ptr = *pmy_chain) != old_chain)
00153     {
00154       *pmy_chain = ptr->next;   /* Do this first in case of recursion.  */
00155       (*ptr->function) (ptr->arg);
00156       if (ptr->free_arg)
00157         (*ptr->free_arg) (ptr->arg);
00158       xfree (ptr);
00159     }
00160 }
00161 
00162 /* Return a value that can be passed to do_cleanups, do_final_cleanups to
00163    indicate perform all cleanups.  */
00164 
00165 struct cleanup *
00166 all_cleanups (void)
00167 {
00168   return SENTINEL_CLEANUP;
00169 }
00170 
00171 /* Discard cleanups and do the actions they describe
00172    until we get back to the point OLD_CHAIN in the cleanup_chain.  */
00173 
00174 void
00175 do_cleanups (struct cleanup *old_chain)
00176 {
00177   do_my_cleanups (&cleanup_chain, old_chain);
00178 }
00179 
00180 /* Discard cleanups and do the actions they describe
00181    until we get back to the point OLD_CHAIN in the final_cleanup_chain.  */
00182 
00183 void
00184 do_final_cleanups (struct cleanup *old_chain)
00185 {
00186   do_my_cleanups (&final_cleanup_chain, old_chain);
00187 }
00188 
00189 /* Main worker routine to discard cleanups.
00190    PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
00191    OLD_CHAIN is the result of a "make" cleanup routine.
00192    Cleanups are discarded until we get back to the old end of the chain.  */
00193 
00194 static void
00195 discard_my_cleanups (struct cleanup **pmy_chain,
00196                      struct cleanup *old_chain)
00197 {
00198   struct cleanup *ptr;
00199 
00200   while ((ptr = *pmy_chain) != old_chain)
00201     {
00202       *pmy_chain = ptr->next;
00203       if (ptr->free_arg)
00204         (*ptr->free_arg) (ptr->arg);
00205       xfree (ptr);
00206     }
00207 }
00208 
00209 /* Discard cleanups, not doing the actions they describe,
00210    until we get back to the point OLD_CHAIN in the cleanup chain.  */
00211 
00212 void
00213 discard_cleanups (struct cleanup *old_chain)
00214 {
00215   discard_my_cleanups (&cleanup_chain, old_chain);
00216 }
00217 
00218 /* Discard final cleanups, not doing the actions they describe,
00219    until we get back to the point OLD_CHAIN in the final cleanup chain.  */
00220 
00221 void
00222 discard_final_cleanups (struct cleanup *old_chain)
00223 {
00224   discard_my_cleanups (&final_cleanup_chain, old_chain);
00225 }
00226 
00227 /* Main worker routine to save cleanups.
00228    PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
00229    The chain is emptied and the result is a pointer to the old chain.  */
00230 
00231 static struct cleanup *
00232 save_my_cleanups (struct cleanup **pmy_chain)
00233 {
00234   struct cleanup *old_chain = *pmy_chain;
00235 
00236   *pmy_chain = SENTINEL_CLEANUP;
00237   return old_chain;
00238 }
00239 
00240 /* Set the cleanup_chain to 0, and return the old cleanup_chain.  */
00241 
00242 struct cleanup *
00243 save_cleanups (void)
00244 {
00245   return save_my_cleanups (&cleanup_chain);
00246 }
00247 
00248 /* Set the final_cleanup_chain to 0, and return the old
00249    final_cleanup_chain.  */
00250 
00251 struct cleanup *
00252 save_final_cleanups (void)
00253 {
00254   return save_my_cleanups (&final_cleanup_chain);
00255 }
00256 
00257 /* Main worker routine to save cleanups.
00258    PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
00259    The chain is restored from CHAIN.  */
00260 
00261 static void
00262 restore_my_cleanups (struct cleanup **pmy_chain, struct cleanup *chain)
00263 {
00264   if (*pmy_chain != SENTINEL_CLEANUP)
00265     internal_warning (__FILE__, __LINE__,
00266                       _("restore_my_cleanups has found a stale cleanup"));
00267 
00268   *pmy_chain = chain;
00269 }
00270 
00271 /* Restore the cleanup chain from a previously saved chain.  */
00272 
00273 void
00274 restore_cleanups (struct cleanup *chain)
00275 {
00276   restore_my_cleanups (&cleanup_chain, chain);
00277 }
00278 
00279 /* Restore the final cleanup chain from a previously saved chain.  */
00280 
00281 void
00282 restore_final_cleanups (struct cleanup *chain)
00283 {
00284   restore_my_cleanups (&final_cleanup_chain, chain);
00285 }
00286 
00287 /* Provide a known function that does nothing, to use as a base for
00288    a possibly long chain of cleanups.  This is useful where we
00289    use the cleanup chain for handling normal cleanups as well as dealing
00290    with cleanups that need to be done as a result of a call to error().
00291    In such cases, we may not be certain where the first cleanup is, unless
00292    we have a do-nothing one to always use as the base.  */
00293 
00294 void
00295 null_cleanup (void *arg)
00296 {
00297 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines