From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 27297 invoked by alias); 3 Jul 2007 18:13:34 -0000 Received: (qmail 27283 invoked by uid 22791); 3 Jul 2007 18:13:33 -0000 X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.4) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 03 Jul 2007 18:13:31 +0000 Received: (qmail 10208 invoked from network); 3 Jul 2007 18:06:48 -0000 Received: from unknown (HELO localhost) (jimb@127.0.0.2) by mail.codesourcery.com with ESMTPA; 3 Jul 2007 18:06:48 -0000 To: Eli Zaretskii Cc: "Michael Snyder" , drow@false.org, Michael.Snyder@access-company.com, gdb-patches@sourceware.org Subject: Re: [OB] Add cleanup, source.c References: <9270.12.7.175.2.1183069663.squirrel@webmail.sonic.net> <20070628224815.GC12578@caradoc.them.org> <655C3D4066B7954481633935A40BB36F041427@ussunex02.svl.access-company.com> <20070628231153.GA14231@caradoc.them.org> <11470.12.7.175.2.1183080998.squirrel@webmail.sonic.net> <20070629113407.GA13561@caradoc.them.org> <003201c7ba8c$d6e0e840$677ba8c0@sonic.net> <000b01c7bb2f$d88684e0$677ba8c0@sonic.net> From: Jim Blandy Date: Tue, 03 Jul 2007 18:13:00 -0000 In-Reply-To: (Eli Zaretskii's message of "Sat, 30 Jun 2007 21:22:01 +0300") Message-ID: User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2007-07/txt/msg00076.txt.bz2 What's going on here is that GDB uses one construct, cleanups, to implement two different useful behaviors, and does so in a perilous way. In Java, you can write: try { ...; } catch { ...; } Or: try { ...; } finally { ...; } The 'catch' block gets executed if the 'try' block throws an exception. The 'finally' block gets executed no matter whether the try block terminates normally or throws an exception. In GDB, when we push cleanups that we intend to discard on success, those are playing the role of a 'catch' block. When we push cleanups that we're counting on being called even if things go wrong, then they're playing the role of a 'finally' block. They're both useful features, and they're definitely not the same feature, because 'finally' blocks get called in more cases. The problem with GDB is that we decide how to treat the blocks when we clean up, not when we register. So here's the case we've been talking about: foo () { make_cleanup (a 'finally' action) do stuff which may throw an error don't call do_cleanups, on at least one path out of the function } bar () { make_cleanup (a 'catch' action) foo () discard_cleanups, since we've succeeded and we don't want our catch action to run } Here, if no errors occur, foo's finally action won't get run because bar's discard_cleanups call applies more broadly than the author of 'bar' intended. What GDB should do instead is this: foo () { finally_handler (a 'finally' action) do stuff which may throw an error don't call do_cleanups, at least one one path out } bar () { failure_handler (a 'failure' action) foo () cleanup_on_success () } where 'cleanup_success' discards failure handlers and runs finally handlers. The 'error' function would call a companion to that named 'cleanup_on_failure', which runs both finally and failure handlers. So. Only 270 calls to 'do_cleanups' and 47 calls to 'discard_cleanups' to examine.