* Re: __attribute__((cleanup(function)) versus try/finally @ 2003-05-13 21:33 Richard Kenner 2003-05-13 22:11 ` Richard Henderson 0 siblings, 1 reply; 52+ messages in thread From: Richard Kenner @ 2003-05-13 21:33 UTC (permalink / raw) To: rth; +Cc: gcc > In any case, there are some semantics to be defined; if a cleanup throws > an exception, what happens? At present, the old exception doesn't get destroyed, and the new exception propagates. I'm not really sure *what* should be said except that it's undefined behaviour. Just FYI, in Ada this is defined and the action depends on how the cleanup was invoked. ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-13 21:33 __attribute__((cleanup(function)) versus try/finally Richard Kenner @ 2003-05-13 22:11 ` Richard Henderson 0 siblings, 0 replies; 52+ messages in thread From: Richard Henderson @ 2003-05-13 22:11 UTC (permalink / raw) To: Richard Kenner; +Cc: gcc On Tue, May 13, 2003 at 05:38:19PM -0400, Richard Kenner wrote: > Just FYI, in Ada this is defined and the action depends on how the > cleanup was invoked. C++ and Java define this as well (though differently). There's certainly ample functionality in except.c to handle this in any way that Ada would like. Mark's question concerned C. r~ ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally
@ 2003-05-09 9:54 Ranjit Mathew
2003-05-09 10:16 ` Andrew Haley
0 siblings, 1 reply; 52+ messages in thread
From: Ranjit Mathew @ 2003-05-09 9:54 UTC (permalink / raw)
To: aph; +Cc: gcc
> > > > The __finally block is executed in case of both "normal" C++
>exceptions
> > > > as well as "faults" such as accessing a NULL pointer, dividing by
>zero,
> > > > etc.
> > >
> > >And your point is... ? Libjava does this for dwarf2 EH on Linux.
> >
> > Yes, I know (http://gcc.gnu.org/java/port-signals.html).
>
>Oh no, that page is way, way out of date. I must rewrite it.
>There's not even any mention of MD_FALLBACK_FRAME_STATE_FOR, which is
>the crucial part of the job.
Maybe laymen aren't supposed to be implementing MAKE_THROW_FRAME for
libgcj ;-), but I think it should at least be pointed out that the crucial
reasons
the given example works *at all* are that:
1. Linux does not care if the signal handler returns or not (unlike
Windows).
2. A proper MD_FALLBACK_FRAME_STATE_FOR definition for Linux/x86 ensures
that unwinding works through the intervening signal handler frame when a
"throw" occurs, instead of aborting the process with an uncerimonious
"abnormal program termination" as would have happened otherwise.
Ranjit.
_________________________________________________________________
Want to get married? Try online matrimony.
http://server1.msn.co.in/features/onlinematrimony/index.asp It's cool.
^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-09 9:54 Ranjit Mathew @ 2003-05-09 10:16 ` Andrew Haley 2003-05-09 12:08 ` Fergus Henderson 2003-05-09 12:49 ` Jamie Lokier 0 siblings, 2 replies; 52+ messages in thread From: Andrew Haley @ 2003-05-09 10:16 UTC (permalink / raw) To: Ranjit Mathew; +Cc: gcc Ranjit Mathew writes: > > > > > The __finally block is executed in case of both "normal" C++ > >exceptions > > > > > as well as "faults" such as accessing a NULL pointer, dividing by > >zero, > > > > > etc. > > > > > > > >And your point is... ? Libjava does this for dwarf2 EH on Linux. > > > > > > Yes, I know (http://gcc.gnu.org/java/port-signals.html). > > > >Oh no, that page is way, way out of date. I must rewrite it. > >There's not even any mention of MD_FALLBACK_FRAME_STATE_FOR, which is > >the crucial part of the job. > > Maybe laymen aren't supposed to be implementing MAKE_THROW_FRAME for > libgcj ;-), but I think it should at least be pointed out that the crucial > reasons > the given example works *at all* are that: > > 1. Linux does not care if the signal handler returns or not (unlike > Windows). Actually, the C standard is quite explicit about this: signal handlers may return either by a return statement of calling longjmp(). Maybe the Windows version of longjmp() does some magic to make this work. > 2. A proper MD_FALLBACK_FRAME_STATE_FOR definition for Linux/x86 Or for any other OS, for that matter. The trouble with doing MD_FALLBACK_FRAME_STATE_FOR for other OSs is that it necessarily requires knowledge of kernel data structures. > ensures that unwinding works through the intervening signal > handler frame when a "throw" occurs, instead of aborting the > process with an uncerimonious "abnormal program termination" as > would have happened otherwise. Actually, that example was written before MD_FALLBACK_FRAME_STATE_FOR, as was the whole page. That's why it's so inaccurate. Andrew. ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-09 10:16 ` Andrew Haley @ 2003-05-09 12:08 ` Fergus Henderson 2003-05-09 12:49 ` Jamie Lokier 1 sibling, 0 replies; 52+ messages in thread From: Fergus Henderson @ 2003-05-09 12:08 UTC (permalink / raw) To: Andrew Haley; +Cc: Ranjit Mathew, gcc On 09-May-2003, Andrew Haley <aph@redhat.com> wrote: > Actually, the C standard is quite explicit about this: signal handlers > may return either by a return statement of calling longjmp(). [I think you meant to say "or" instead of "of".] What you say is true to some extent, but it only applies to signal handlers for synchronous signals, i.e. those caused by an explicit call to abort() or raise(). For asynchronous signals, the behaviour is undefined if the signal handler calls longjmp(), due to C99 7.14.1.1 paragraph 5, which prohibits such signal handlers from calling *any* standard library function other than abort(), _Exit(), or signal(): | If the signal occurs other than as the result of | calling the abort or raise function, the behavior is | undefined if the signal handler refers to any object with | static storage duration other than by assigning a value to | an object declared as volatile sig_atomic_t, or the signal | handler calls any function in the standard library other | than the abort function, the _Exit function, or the signal | function with the first argument equal to the signal number | corresponding to the signal that caused the invocation of | the handler. -- Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp. ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-09 10:16 ` Andrew Haley 2003-05-09 12:08 ` Fergus Henderson @ 2003-05-09 12:49 ` Jamie Lokier 1 sibling, 0 replies; 52+ messages in thread From: Jamie Lokier @ 2003-05-09 12:49 UTC (permalink / raw) To: Andrew Haley; +Cc: Ranjit Mathew, gcc Andrew Haley wrote: > > 1. Linux does not care if the signal handler returns or not (unlike > > Windows). > > Actually, the C standard is quite explicit about this: signal handlers > may return either by a return statement of calling longjmp(). Maybe > the Windows version of longjmp() does some magic to make this work. Last time I tried it (a few years ago now), longjmp() out of a signal handler which is interrupting a select() system call crashed Cygwin. So, I had to use a different strategy for picking up SIGCHLD events on that platform - limiting select() calls to a maximum timeout of a few seconds. -- Jamie ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally @ 2003-05-09 9:23 Ranjit Mathew 2003-05-09 9:31 ` Andrew Haley 0 siblings, 1 reply; 52+ messages in thread From: Ranjit Mathew @ 2003-05-09 9:23 UTC (permalink / raw) To: rth; +Cc: gcc > > The __finally block is executed in case of both "normal" C++ exceptions > > as well as "faults" such as accessing a NULL pointer, dividing by zero, > > etc. > >And your point is... ? Libjava does this for dwarf2 EH on Linux. Yes, I know (http://gcc.gnu.org/java/port-signals.html). The Windows port of GCJ also has a similar hack using SEH Win32 APIs. However, unlike signal handlers on Linux, Windows actually expects the "UnexpectedExceptionHandler" routine to *return* with a value to it - since the current implementation doesn't, a simple thing like two Java NullPointerExceptions results in a hung process on Win2K! So if we manage to make it work reliably, we can then claim identical semantics indeed. Touche. >Incidentally, I would be willing to review and incorporate pieces >of this into gcc. > >I can't promise anything about "__except" or "__leave" (indeed, I >suspect that they _won't_ be incorporated), but we can at least talk >about including SEH for general exception handling. At minimum you'd >be able to use catch(...) instead of "__except" in C++. This is good news for all MinGW users, thank you! Casper Hornstrup (chorns at users dot sourceforge dot net) of the ReactOS team, who has created the SEH enabled GCC mentioned earlier, would be delighted to hear this I think. Ranjit. _________________________________________________________________ Dreaming of a holiday? Make it happen. http://server1.msn.co.in/sp03/switzerlandtourism/index.asp In Switzerland! ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-09 9:23 Ranjit Mathew @ 2003-05-09 9:31 ` Andrew Haley 0 siblings, 0 replies; 52+ messages in thread From: Andrew Haley @ 2003-05-09 9:31 UTC (permalink / raw) To: Ranjit Mathew; +Cc: rth, gcc Ranjit Mathew writes: > > > The __finally block is executed in case of both "normal" C++ exceptions > > > as well as "faults" such as accessing a NULL pointer, dividing by zero, > > > etc. > > > >And your point is... ? Libjava does this for dwarf2 EH on Linux. > > Yes, I know (http://gcc.gnu.org/java/port-signals.html). Oh no, that page is way, way out of date. I must rewrite it. There's not even any mention of MD_FALLBACK_FRAME_STATE_FOR, which is the crucial part of the job. Andrew. ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally @ 2003-05-08 7:49 Ranjit Mathew 2003-05-08 21:21 ` Richard Henderson 0 siblings, 1 reply; 52+ messages in thread From: Ranjit Mathew @ 2003-05-08 7:49 UTC (permalink / raw) To: gcc > > The same issue was pointed out (albeit in passing) > > when Aldy Hernandez had submitted his __try/__finally > > patch to GCC for C. > >And I responded at the time claiming that the semantics of >the two extensions are identical. Very similar, but not identical, AFAICT: http://msdn.microsoft.com/library/en-us/vccelng/htm/state_14.asp The __finally block is executed in case of both "normal" C++ exceptions as well as "faults" such as accessing a NULL pointer, dividing by zero, etc. Of course this would tie in with integrating SEH support into GCC, a brave attempt at which can be found at: http://reactos.wox.org/index.php?page=gccseh in which case my point becomes moot. > > Since the Win32 API stack does not have DW2 EH > > unwind information, the program just terminates > > when an exception is thrown (if using DW2 EH). > > > > SJLJ does not have any such problems. > > > > In fact, this seems to be a fundamental limitation > > of the DW2 EH mechanism and not just on Windows. > >Yes. Such is the price you pay for not saving all of the >registers up front when an exception is *not* thrown. IIRC, till some time ago "-fsjlj-exceptions" used to be available that should allow such fringe cases to work albeit with a performance hit. Otherwise DW2 EH is *way better* than SJLJ as you all know very well and should be the default. Does anyone know why "fsjlj-exceptions" support was dropped and made a configure time option? > > MD_FALLBACK_FRAME_STATE_FOR looks a bit promising > > but how do we generalise it to any "foreign" caller? > >Eh, MD_FALLBACK_FRAME_STATE_FOR isn't really generalizable. >You could perhaps hack it to parse SEH unwind data, but... SEH is an SJLJ type scheme: http://www.microsoft.com/msj/0197/Exception/Exception.aspx >Another possibility is to give up on unwind-dw2.c entirely >and write a new unwinder that uses the SEH bits in the Win32 >API directly, all the time. Then (1) you'd be able to unwind >through Windows routines and (2) there'd be no "confusion" >about the supposed "differences" in try/finally. Possible, but it feels awful to throw away the fantastic DW2 EH... :-( Ranjit. _________________________________________________________________ Dreaming of a holiday? Make it happen. http://server1.msn.co.in/sp03/switzerlandtourism/index.asp In Switzerland! ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-08 7:49 Ranjit Mathew @ 2003-05-08 21:21 ` Richard Henderson 0 siblings, 0 replies; 52+ messages in thread From: Richard Henderson @ 2003-05-08 21:21 UTC (permalink / raw) To: Ranjit Mathew; +Cc: gcc On Thu, May 08, 2003 at 01:19:23PM +0530, Ranjit Mathew wrote: > The __finally block is executed in case of both "normal" C++ exceptions > as well as "faults" such as accessing a NULL pointer, dividing by zero, > etc. And your point is... ? Libjava does this for dwarf2 EH on Linux. > Of course this would tie in with integrating SEH support into GCC, > a brave attempt at which can be found at: > > http://reactos.wox.org/index.php?page=gccseh > > in which case my point becomes moot. Exactly. Incidentally, I would be willing to review and incorporate pieces of this into gcc. I can't promise anything about "__except" or "__leave" (indeed, I suspect that they _won't_ be incorporated), but we can at least talk about including SEH for general exception handling. At minimum you'd be able to use catch(...) instead of "__except" in C++. > Does anyone know why "fsjlj-exceptions" support was > dropped and made a configure time option? The runtime libraries can't handle both at once. > SEH is an SJLJ type scheme: > > http://www.microsoft.com/msj/0197/Exception/Exception.aspx That's too bad. Not *horrible* given that x86 only has 3 call-saved registers, but... r~ ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally @ 2003-05-07 10:18 Ranjit Mathew 2003-05-07 13:54 ` Jason Merrill ` (2 more replies) 0 siblings, 3 replies; 52+ messages in thread From: Ranjit Mathew @ 2003-05-07 10:18 UTC (permalink / raw) To: jason; +Cc: gcc > 2) implementing something before standardization > > That's why the patch doesn't create "try" and "finally" keywords, but > rather "__try" and "__finally". Though I can't imagine any similar > construct having different semantics. Sorry to butt in into this discussion, but I would like to point out that it would be a BAD idea to name these "__try/__finally" simply because these are used in the Windows world to deal with Windows Structured Exception Handling (SEH) and are a language extension introduced by MS Visual C/C++ (and adopted by other commercial compilers for Windows): http://msdn.microsoft.com/library/en-us/vccelng/htm/statem_31.asp There are quite a few commercial and non-commercial programs out there that use these keywords. However unfortunate you consider this situation to be, if GCC introduces these keywords, it is going to create a lot of confusion. The same issue was pointed out (albeit in passing) when Aldy Hernandez had submitted his __try/__finally patch to GCC for C. Now I have an issue somewhat related to this discussion that I hope someone would be able to shed some light on: on Windows, the Cygwin/MinGW targets have had to give up on DW2 EH in favour of SJLJ purely because exceptions could not be thrown from a callback function, across the Windows Event Dispatcher stack to the handler of the exception. Such code is common in Windows GUI applications created with GCC (MinGW). The "core" message loop of such Windows GUI programs is roughly like the following: while( GetMessage( &msg, NULL, 0, 0)) { try { TranslateMessage( &msg); DispatchMessage( &msg); } catch (...) { /* Whatever */ } } DispatchMessage( ) is a Win32 API that ultimately delivers the message to a registered "window procedure" callback function within the application that handles this message and might possibly throw an exception. Since the Win32 API stack does not have DW2 EH unwind information, the program just terminates when an exception is thrown (if using DW2 EH). SJLJ does not have any such problems. In fact, this seems to be a fundamental limitation of the DW2 EH mechanism and not just on Windows. So is there a way out of this? MD_FALLBACK_FRAME_STATE_FOR looks a bit promising but how do we generalise it to any "foreign" caller? Many thanks in advance for answering these. Ranjit. -- Ranjit Mathew Email: rmathew AT hotmail DOT com Bangalore, INDIA. Web: http://ranjitmathew.tripod.com/ ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-07 10:18 Ranjit Mathew @ 2003-05-07 13:54 ` Jason Merrill 2003-05-07 18:23 ` Richard Henderson 2003-05-08 18:02 ` Mike Stump 2 siblings, 0 replies; 52+ messages in thread From: Jason Merrill @ 2003-05-07 13:54 UTC (permalink / raw) To: Ranjit Mathew; +Cc: gcc On Wed, 07 May 2003 15:49:06 +0530, Ranjit Mathew <rmathew@hotmail.com> wrote: > Sorry to butt in into this discussion, but I would like to point out that > it would be a BAD idea to name these "__try/__finally" simply because > these are used in the Windows world to deal with Windows Structured > Exception Handling (SEH) and are a language extension introduced by MS > Visual C/C++ (and adopted by other commercial compilers for Windows): >[...] > However unfortunate you consider this situation to be, if GCC introduces > these keywords, it is going to create a lot of confusion. Why would it cause confusion? The VC++ version has the same semantics. > Now I have an issue somewhat related to this discussion that I hope > someone would be able to shed some light on: on Windows, the Cygwin/MinGW > targets have had to give up on DW2 EH in favour of SJLJ purely because > exceptions could not be thrown from a callback function, across the > Windows Event Dispatcher stack to the handler of the exception. >[...] > Since the Win32 API stack does not have DW2 EH > unwind information, the program just terminates > when an exception is thrown (if using DW2 EH). Sure. > In fact, this seems to be a fundamental limitation of the DW2 EH > mechanism and not just on Windows. Yes, any callback API would have similar problems if the dispatcher is not compiled with -fexceptions. > So is there a way out of this? > > MD_FALLBACK_FRAME_STATE_FOR looks a bit promising but how do we > generalise it to any "foreign" caller? This is difficult on the x86; you would need to scan back to the beginning of the function and disassemble the function prologue to find out where registers are saved. You could probably use some code from gdb as a starting point. Jason ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-07 10:18 Ranjit Mathew 2003-05-07 13:54 ` Jason Merrill @ 2003-05-07 18:23 ` Richard Henderson 2003-05-08 18:02 ` Mike Stump 2 siblings, 0 replies; 52+ messages in thread From: Richard Henderson @ 2003-05-07 18:23 UTC (permalink / raw) To: Ranjit Mathew; +Cc: jason, gcc On Wed, May 07, 2003 at 03:49:06PM +0530, Ranjit Mathew wrote: > The same issue was pointed out (albeit in passing) > when Aldy Hernandez had submitted his __try/__finally > patch to GCC for C. And I responded at the time claiming that the semantics of the two extensions are identical. > Since the Win32 API stack does not have DW2 EH > unwind information, the program just terminates > when an exception is thrown (if using DW2 EH). > > SJLJ does not have any such problems. > > In fact, this seems to be a fundamental limitation > of the DW2 EH mechanism and not just on Windows. Yes. Such is the price you pay for not saving all of the registers up front when an exception is *not* thrown. > MD_FALLBACK_FRAME_STATE_FOR looks a bit promising > but how do we generalise it to any "foreign" caller? Eh, MD_FALLBACK_FRAME_STATE_FOR isn't really generalizable. You could perhaps hack it to parse SEH unwind data, but... Another possibility is to give up on unwind-dw2.c entirely and write a new unwinder that uses the SEH bits in the Win32 API directly, all the time. Then (1) you'd be able to unwind through Windows routines and (2) there'd be no "confusion" about the supposed "differences" in try/finally. r~ ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-07 10:18 Ranjit Mathew 2003-05-07 13:54 ` Jason Merrill 2003-05-07 18:23 ` Richard Henderson @ 2003-05-08 18:02 ` Mike Stump 2 siblings, 0 replies; 52+ messages in thread From: Mike Stump @ 2003-05-08 18:02 UTC (permalink / raw) To: Ranjit Mathew; +Cc: jason, gcc On Wednesday, May 7, 2003, at 03:19 AM, Ranjit Mathew wrote: > Now I have an issue somewhat related to this > discussion that I hope someone would be able to > shed some light on: on Windows, the Cygwin/MinGW > targets have had to give up on DW2 EH in favour of > SJLJ purely because exceptions could not be > thrown from a callback function, across the > Windows Event Dispatcher stack to the handler > of the exception. This can be made to work given an integrated sjlj/dwarf2 EH scheme. At transition points into and out of code compiled by other compilation systems (or -fno-exception code), we introduce a sjlj cleanup point there. For, take for example: foo() { DispatchMessage(); } we have to know that DispatchMessage is going to go to `outside', imagine if you will: #pragma gcc EH doesnt have unwind tables: DispatchMessage foo() { ... DispatchMessage(); ... } then it is a simple process to generate: foo() { ... sjljtry { DispatchMessage(); } catch (...) { rethrow; } ... } instead. We can get back `into' the unwind tables by doing the lj back to this point. > In fact, this seems to be a fundamental limitation > of the DW2 EH mechanism and not just on Windows. An unimplemented feature, I'd say, not a fundamental limitation. Though, such a change would be probably have ABI impact, as only the enhanced thrower would be able to fall back to doing the throw when it runs out of unwind information. ^ permalink raw reply [flat|nested] 52+ messages in thread
[parent not found: <Pine.BSF.4.55.0305061457450.57349@acrux.dbai.tuwien.ac.at>]
[parent not found: <1052245742.2583.315.camel@doubledemon.codesourcery.com>]
[parent not found: <wvlissnc2e3.fsf@prospero.boston.redhat.com>]
[parent not found: <1052249890.31850.338.camel@doubledemon.codesourcery.com>]
* Re: __attribute__((cleanup(function)) versus try/finally [not found] ` <1052249890.31850.338.camel@doubledemon.codesourcery.com> @ 2003-05-06 21:04 ` Jason Merrill 2003-05-06 21:24 ` Mark Mitchell ` (2 more replies) 0 siblings, 3 replies; 52+ messages in thread From: Jason Merrill @ 2003-05-06 21:04 UTC (permalink / raw) To: Mark Mitchell; +Cc: gcc, Jason Merrill On 06 May 2003 12:38:09 -0700, Mark Mitchell <mark@codesourcery.com> wrote: >> In any case, how are you thinking to do this? You've mentioned such a >> thing before, but I haven't noticed an implementation sketch. > > I did on the gcc list, but it got lost in the noise, I think. > > The strategy is: > > (1) Have pthread_cleanup_push include the current $sp in the cleanup > record. Otherwise, use the same data structures currently used by > glibc's pthread_cleanup_push. > > (2) When an exception is thrown: > > - Figure out where the next handler/cleanup will be. > > (By hypothesis, this is not going to be in C code, because we don't > have try/finally in C.) > > - If unwinding the stack to that destination will result in $sp be older > than the $sp recorded in the cleanup at the top of the C cleanup stack, > run C cleanups until that is no longer true. > - Transfer control to the handler as is done now. Hmm, I suppose you can assume that $sp is linear. I guess that would work, except that you can't unwind through C unless the C code has unwind info. If you assume that you won't be trying to unwind through C code without unwind info into C++ code, this still requires that you handle the cancellation exception specially. When you run out of unwind info, rather than call terminate you need to hand off to the old pthread_exit. Of course, that could be implemented by setting the terminate_handler field in the exception header, but then you'd call it in all situations where you would otherwise call terminate. And if you need to handle unwinding out to C++ code in some cases, you might as well always use the same technique. Regardless of what we do about C cleanups, any C code which both calls cancellation points and is called from C++ must have unwind info. Otherwise we lose the C++ cleanups (and we can't catch the cancellation exception, as you've been asking for). In effect, this means that any library code that does I/O must have unwind info. At that point, it seems to me that we might as well always emit it, since it only costs us in disk space. That's what Tru64 does. And Irix. A compromise would be for -pthreads to imply -fexceptions. >> > The try/finally solution cannot be implemented with this same >> > performance; it will, in fact, exact a performance price, in terms of >> > both code space and the speed at which cleanups are run, on all >> > systems. On systems with setjmp/longjmp exceptions, both costs will be >> > very high indeed. I think you're exaggerating the costs. This is the way the C++ frontend works, and you only incur the costs when you use the feature. The design philosophy of EH has always been that the speed of the normal code is what matters, not the cleanups. >> Hmm. Are you talking about representing cleanups in the LSDA via a >> function pointer and a CFA offset for the argument object? That way you >> still need unwind info and PC range tables, but you don't put any code into >> the function itself. > > I'm not as sophisticated as you about this; I don't actually know what > all the EH implementation details are. With the scheme above, you do > still need PC range tables and (some?) unwind information, but you don't > put any code into the function. I keep mumbling that I think you might > be able to avoid some of the unwind information for C, but I've never > done what it would take to prove or disprove that assertion. > The key point is that you don't need any handler code in the function. I'm not sure why that's key. Exception handlers in the function can be moved aside to improve cache locality. I think we already do this. > The observation behind this is that pthread cleanups -- unlike C++ catch > clauses -- do not need to execute in the frame of the function that > pushed them. They just need to execute while the stack is still there, > in case the "arg" to the function directly or indirectly references > stuff on the stack. No, they don't need to. Nor do C++ destructors. But they do anyway. If we decide that moving cleanup calls out of line is an important optimization, doing it via analysis of the cleanup expression would allow C++ and Java to benefit from it as well. One major practical problem with attribute(cleanup): It doesn't map very well onto pthread_cleanup_push. With attribute(cleanup) the cleanup argument is the variable to which the attribute is attached, but with pthread_cleanup_push, the cleanup argument is usually a local variable which has already been declared, so you need to indirect through another function. It seems to me that a lot of your objections come from resistance to letting EH into C. But if we want to interleave pthread and C++ cleanups, we don't have any choice. Jason ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-06 21:04 ` Jason Merrill @ 2003-05-06 21:24 ` Mark Mitchell 2003-05-07 21:21 ` Jason Merrill 2003-05-06 21:52 ` Anthony Green 2003-05-08 17:44 ` Mike Stump 2 siblings, 1 reply; 52+ messages in thread From: Mark Mitchell @ 2003-05-06 21:24 UTC (permalink / raw) To: Jason Merrill; +Cc: gcc > Hmm, I suppose you can assume that $sp is linear. I guess that would work, > except that you can't unwind through C unless the C code has unwind info. The C code must have unwind info -- but it does not need to have handler code. Moving the handler code out-of-line is only part of the issue; the code size is the other issue. > cancellation exception specially. When you run out of unwind info, rather > than call terminate you need to hand off to the old pthread_exit. I had suggested simply having the pthread-launching routine (the first thing called in the new thread) be written in C++. It can then just catch the exception and do whatever's required. > In effect, this means that any library code that does I/O must have unwind > info. At that point, it seems to me that we might as well always emit it, > since it only costs us in disk space. That's what Tru64 does. And Irix. Yes, I don't argue with any of this. It would be nice to avoid unwind info, but I'm not sure we can. We can avoid handlers, however. > >> > The try/finally solution cannot be implemented with this same > >> > performance; it will, in fact, exact a performance price, in terms of > >> > both code space and the speed at which cleanups are run, on all > >> > systems. On systems with setjmp/longjmp exceptions, both costs will be > >> > very high indeed. > > I think you're exaggerating the costs. This is the way the C++ frontend > works, and you only incur the costs when you use the feature. The design > philosophy of EH has always been that the speed of the normal code is what > matters, not the cleanups. With setjmp/longjmp, there are big costs even if you don't use the feature. With the scheme I propose, you shouldn't need as many setjmps -- you only need one setjmp at the beginning of the function to be able to unwind. You never need to land in the middle of the function. Without setjmp/longjmp, you save mostly code space. You also improve cleanup time (in that you need not transfer control to the local frame of the function before running the cleanup), but this is a smaller advantage. > > The observation behind this is that pthread cleanups -- unlike C++ catch > > clauses -- do not need to execute in the frame of the function that > > pushed them. They just need to execute while the stack is still there, > > in case the "arg" to the function directly or indirectly references > > stuff on the stack. > > No, they don't need to. Nor do C++ destructors. But they do anyway. Catch-clauses and destructors are different. Given: int i; try { ... } catch (...) { i = 3; } the catch-clause had better execute in the frame of this function. With a destructor or (analogously) a pthread cleanup handler, the execution just has to take place while the frame is still active. -- Mark Mitchell CodeSourcery, LLC mark@codesourcery.com ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-06 21:24 ` Mark Mitchell @ 2003-05-07 21:21 ` Jason Merrill 2003-05-07 22:18 ` Mark Mitchell 0 siblings, 1 reply; 52+ messages in thread From: Jason Merrill @ 2003-05-07 21:21 UTC (permalink / raw) To: Mark Mitchell; +Cc: gcc, Jason Merrill On 06 May 2003 14:24:49 -0700, Mark Mitchell <mark@codesourcery.com> wrote: >> cancellation exception specially. When you run out of unwind info, rather >> than call terminate you need to hand off to the old pthread_exit. > > I had suggested simply having the pthread-launching routine (the first > thing called in the new thread) be written in C++. It can then just > catch the exception and do whatever's required. Sure, that works so long as you don't run out of unwind info. >> >> > The try/finally solution cannot be implemented with this same >> >> > performance; it will, in fact, exact a performance price, in terms of >> >> > both code space and the speed at which cleanups are run, on all >> >> > systems. On systems with setjmp/longjmp exceptions, both costs will be >> >> > very high indeed. >> >> I think you're exaggerating the costs. This is the way the C++ frontend >> works, and you only incur the costs when you use the feature. The design >> philosophy of EH has always been that the speed of the normal code is what >> matters, not the cleanups. > > With setjmp/longjmp, there are big costs even if you don't use the > feature. There are no costs unless there are cleanups. > With the scheme I propose, you shouldn't need as many setjmps -- you only > need one setjmp at the beginning of the function to be able to unwind. > You never need to land in the middle of the function. The C++ setjmp/longjump EH scheme also only requires one setjmp per function unless there are nested catches; the EH runtime jumps there, runs all the cleanups for the current function, and calls back into the unwinder. > Without setjmp/longjmp, you save mostly code space. You also improve > cleanup time (in that you need not transfer control to the local frame > of the function before running the cleanup), but this is a smaller > advantage. Which may or may not outweigh the advantages of having the cleanups in the function (code motion into the landing pad, inlining destructors, not forcing the argument into the stack). How to run simple cleanups (a call to a function which takes a pointer to an object in the current frame) is an optimization question. We already have to handle more complex cleanups for Java try/finally, and for inlined destructors in C++. Allowing people to write them in C doesn't make our job any harder. >> > The observation behind this is that pthread cleanups -- unlike C++ catch >> > clauses -- do not need to execute in the frame of the function that >> > pushed them. They just need to execute while the stack is still there, >> > in case the "arg" to the function directly or indirectly references >> > stuff on the stack. >> >> No, they don't need to. Nor do C++ destructors. But they do anyway. > > Catch-clauses and destructors are different. I don't disagree. > Given: > > int i; > try { ... } catch (...) { i = 3; } > > the catch-clause had better execute in the frame of this function. > > With a destructor or (analogously) a pthread cleanup handler, the > execution just has to take place while the frame is still active. Well, if you really wanted to, you could turn the catch clause into a nested function which takes an argument pointing to the frame, though you probably wouldn't want to, as it would force all variables used in the catch clause into the stack. My point, however, was that in the current implementation, destructors are run within the frame of the function, even though they don't need to be. We could make a different choice, but again, it's just a question of optimization strategy. The same choices would apply to Java and C. Basically, what I'm saying is that the question of what sorts of cleanups to allow can be separated from the question of how to implement them. If we can set aside the implementation issues, it becomes just a question of language design, and I still think that try/finally is the elegant solution. Jason ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-07 21:21 ` Jason Merrill @ 2003-05-07 22:18 ` Mark Mitchell 2003-05-07 23:01 ` Jason Merrill ` (2 more replies) 0 siblings, 3 replies; 52+ messages in thread From: Mark Mitchell @ 2003-05-07 22:18 UTC (permalink / raw) To: Jason Merrill; +Cc: gcc > There are no costs unless there are cleanups. Yes -- but I'm talking about the situation where there are cleanups. Concretely, consider the following C function: void f() { FILE *f1, *f2, *f3; f1 = fopen ("/tmp/foo"); pthread_cleanup_push (fclose, f1); g(); f2 = fopen ("/tmp/bar"); pthread_cleanup_push (fclose, f2); g(); f3 = fopen ("/tmp/baz"); pthread_cleanup_push (fclose, f3); g (); pthread_cleanup_pop (1); pthread_cleanup_pop (1); pthread_cleanup_pop (1); } Now, with my scheme this function has no handler code; i.e, the EH run-time library will never transfer control back to this function. Even when using setjmp/longjmp the cost is just one setjmp at the start of the function, so that the stack can be unwound. If pthread_cleanup_push uses try/finally, it's my understanding that there will be multiple calls to setjmp, before each of the calls to g. And in the non-setjmp case, there will be landing pads and unwind information for each of the exception regions, rather than just one for the entire function. > > Without setjmp/longjmp, you save mostly code space. You also improve > > cleanup time (in that you need not transfer control to the local frame > > of the function before running the cleanup), but this is a smaller > > advantage. > > Which may or may not outweigh the advantages of having the cleanups in the > function (code motion into the landing pad, inlining destructors, not > forcing the argument into the stack). For pthread_cleanup_push, this is generally not an issue; the cleanup is a function pointer. Unless that function pointer is to an inline function, you're going to make a call here anyhow; there's no real advantage. > Basically, what I'm saying is that the question of what sorts of cleanups > to allow can be separated from the question of how to implement them. If > we can set aside the implementation issues, it becomes just a question of > language design, and I still think that try/finally is the elegant > solution. (There's nothing wrong with try/finally as a construct in the abstract. I'm all for continuations, too! And real closures! If C had templates, objects, exceptions, and namespaces, I'd love it to pieces! Seriously, one of the few remaining objections to programming in C++ has been "exceptions add too much overhead". Once we add unwind tables to C -- as all of our proposals do, including mine -- I'm not really sure what the point of programming in C is going to be any more. Maybe if you really like the fact that "struct S {};" doesn't introduce a typedef, or that "void f()" isn't a prototype. Maybe we should add -fnothing-but-exceptions to G++, and just use that as the C compiler.) Adding EH to C is a very dramatic change. The spirit of C is "no hidden stuff." Calling exceptions "zero-cost" is a lie; we say that because they require no additional instructions be executed unless an exception is thrown, not because they actually have no cost. The unwind tables are a significant cost, for example. To that end, I've toyed with the following idea: - When building a library written in C, provide two sets of entry points for the globally visible functions: a version that is called from C, and a version called from everything else. The non-C version of the entry point calls setjmp. Then, you can unwind through C code with a single longjmp, no unwind tables, no handlers. (You do this by saying "huh, no unwind info for this frame; must be C; call the top entry on the longjmp stack.) You actually only need this setjmp on those entry points that are going to call things that might throw exceptions; in glibc, for example, that means functions that call cancellation points, or take callbacks (ala qsort). - The cost of this scheme for a pure C program is exactly zero. No unwind info, no setjmps, no nothing. You get correct mixed C++/C semantics with slight cost; on entry to a C library from C++ code you take a hit if you need to call setjmp. This kind of solution is awfully attractive if you're on an embedded system. (I want pthreads on my cell-phone, but I sure don't want to have extra unwind info around. I want to be able to support C++, but if it's not in use, I don't want to have to pay the cost of supporting C++ by my making my C libraries bigger.) -- Mark Mitchell CodeSourcery, LLC mark@codesourcery.com ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-07 22:18 ` Mark Mitchell @ 2003-05-07 23:01 ` Jason Merrill 2003-05-08 12:05 ` Gabriel Dos Reis 2003-05-09 5:46 ` Kai Henningsen 2 siblings, 0 replies; 52+ messages in thread From: Jason Merrill @ 2003-05-07 23:01 UTC (permalink / raw) To: Mark Mitchell; +Cc: gcc, Jason Merrill On 07 May 2003 15:18:01 -0700, Mark Mitchell <mark@codesourcery.com> wrote: > Now, with my scheme this function has no handler code; i.e, the EH > run-time library will never transfer control back to this function. Yes. With the alternative look-aside optimization I mentioned, the same would be true. And it wouldn't even require a library call to register the cleanup. > Even when using setjmp/longjmp the cost is just one setjmp at the start > of the function, so that the stack can be unwound. I think the longjmp_unwind scheme uses multiple setjmps, though I'm not sure; it doesn't have the benefit of the whole-function analysis that the compiler can do when inserting EH code. > If pthread_cleanup_push uses try/finally, it's my understanding that > there will be multiple calls to setjmp, before each of the calls to g. I'm pretty sure there's just one at the beginning of the function, emitted if needed. The parallel look-aside optimization for the setjmp case could be to register EH cleanups via a call into the EH runtime much like pthread_cleanup_push; this would avoid the need for any setjmps if a function only has cleanups. > And in the non-setjmp case, there will be landing pads and unwind > information for each of the exception regions, rather than just one for > the entire function. Landing pads, yes, but they're just one instruction unless an optimizer has moved code there, in which case it's presumably beneficial. Unwind info is always per-function. There is, however, an entry in the LSDA for each region, typically 4 bytes in a small function. The look-aside optimization would make this larger, of course. > Adding EH to C is a very dramatic change. The spirit of C is "no hidden > stuff." Calling exceptions "zero-cost" is a lie; we say that because > they require no additional instructions be executed unless an exception > is thrown, not because they actually have no cost. The unwind tables > are a significant cost, for example. Significant, but not unreasonable IMO. As I mentioned, Irix and Tru64 always emit them. We always emit them for S/390 and x86-64. Always emitting them for pthreads code seems appropriate to me, and much easier than creating a whole new system to deal with what is basically an already solved problem. > To that end, I've toyed with the following idea: > > - When building a library written in C, provide two sets of entry points > for the globally visible functions >[...] This sounds like a rather heavy weight solution to this problem. I'd much rather re-use mechanisms we already have. > This kind of solution is awfully attractive if you're on an embedded > system. (I want pthreads on my cell-phone, but I sure don't want to have > extra unwind info around. I want to be able to support C++, but if it's > not in use, I don't want to have to pay the cost of supporting C++ by my > making my C libraries bigger.) Then you probably want to use setjmp/longjmp exceptions. With the optimization described above, it would be no more expensive than the old mechanism. Jason ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-07 22:18 ` Mark Mitchell 2003-05-07 23:01 ` Jason Merrill @ 2003-05-08 12:05 ` Gabriel Dos Reis 2003-05-09 5:46 ` Kai Henningsen 2 siblings, 0 replies; 52+ messages in thread From: Gabriel Dos Reis @ 2003-05-08 12:05 UTC (permalink / raw) To: Mark Mitchell; +Cc: Jason Merrill, gcc Mark Mitchell <mark@codesourcery.com> writes: [...] | Seriously, one of the few remaining objections to programming in C++ has | been "exceptions add too much overhead". Once we add unwind tables to C | -- as all of our proposals do, including mine -- I'm not really sure | what the point of programming in C is going to be any more. Exactly! We should refrain from adding extensions to C or C++ from a short-sighted point of view. At any point we n eed to have the picture in the foreground, or else we would end up in one or two years cursing after the same extensions (Did I mention statement-expression ? :-) | Maybe if | you really like the fact that "struct S {};" doesn't introduce a | typedef, Well, in the C++ front-end there is no reason we should be creating that artificial typedef all around: it wastes memory and unnecessarily complicates routines. -- Gaby ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-07 22:18 ` Mark Mitchell 2003-05-07 23:01 ` Jason Merrill 2003-05-08 12:05 ` Gabriel Dos Reis @ 2003-05-09 5:46 ` Kai Henningsen 2 siblings, 0 replies; 52+ messages in thread From: Kai Henningsen @ 2003-05-09 5:46 UTC (permalink / raw) To: gcc mark@codesourcery.com (Mark Mitchell) wrote on 07.05.03 in <1052345885.5665.64.camel@doubledemon.codesourcery.com>: > Seriously, one of the few remaining objections to programming in C++ has > been "exceptions add too much overhead". Once we add unwind tables to C > -- as all of our proposals do, including mine -- I'm not really sure > what the point of programming in C is going to be any more. To me, the worst thing about C++ is the syntax. As someone who wrote a parser, I'm sure you know better than I where all the skeletons lie. The second worst thing is the concept of "POD" vs. "non-POD" types. This seems expressly designed to violate the principle of least surprise. Exceptions aren't even in the running. Exceptions are something that's present in almost every modern language - but most don't have syntax backtracking, or types both with and without initialization by default (and you can't add it to those that haven't got it without major surgery). Programmer overhead, to me, is much more important than implementation overhead. Especially if the implementation overhead is only on the slow path. MfG Kai ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-06 21:04 ` Jason Merrill 2003-05-06 21:24 ` Mark Mitchell @ 2003-05-06 21:52 ` Anthony Green 2003-05-08 17:44 ` Mike Stump 2 siblings, 0 replies; 52+ messages in thread From: Anthony Green @ 2003-05-06 21:52 UTC (permalink / raw) To: Jason Merrill; +Cc: Mark Mitchell, gcc On Tue, 2003-05-06 at 14:02, Jason Merrill wrote: > Hmm, I suppose you can assume that $sp is linear. I know of one proprietary platform where this is not true. On the other hand, GCC does not currently support this system. FWIW, I strongly support the try/finally proposal. One advantage that hasn't been mentioned is that it may help people migrate from proprietary compilers to GCC. I think that this user-centric argument is compelling just on it's own. AG ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-06 21:04 ` Jason Merrill 2003-05-06 21:24 ` Mark Mitchell 2003-05-06 21:52 ` Anthony Green @ 2003-05-08 17:44 ` Mike Stump 2003-05-08 17:45 ` Jason Merrill 2 siblings, 1 reply; 52+ messages in thread From: Mike Stump @ 2003-05-08 17:44 UTC (permalink / raw) To: Jason Merrill; +Cc: Mark Mitchell, gcc On Tuesday, May 6, 2003, at 02:02 PM, Jason Merrill wrote: > Hmm, I suppose you can assume that $sp is linear. One can track discontinuities in an along side data structure at the discontinuity creation points, and use that to order the comparisons during throw time, should we want to. ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-08 17:44 ` Mike Stump @ 2003-05-08 17:45 ` Jason Merrill 2003-05-08 18:40 ` Mark Mitchell 0 siblings, 1 reply; 52+ messages in thread From: Jason Merrill @ 2003-05-08 17:45 UTC (permalink / raw) To: Mike Stump; +Cc: Mark Mitchell, gcc On Thu, 8 May 2003 10:44:04 -0700, Mike Stump <mrs@apple.com> wrote: > On Tuesday, May 6, 2003, at 02:02 PM, Jason Merrill wrote: >> Hmm, I suppose you can assume that $sp is linear. > > One can track discontinuities in an along side data structure at the > discontinuity creation points, and use that to order the comparisons during > throw time, should we want to. Again, this sort of thing sounds like a cure that's worse than the disease. Jason ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-08 17:45 ` Jason Merrill @ 2003-05-08 18:40 ` Mark Mitchell 2003-05-08 19:06 ` Alexandre Oliva 2003-05-08 19:37 ` Jason Merrill 0 siblings, 2 replies; 52+ messages in thread From: Mark Mitchell @ 2003-05-08 18:40 UTC (permalink / raw) To: Jason Merrill; +Cc: Mike Stump, gcc On Thu, 2003-05-08 at 10:44, Jason Merrill wrote: > On Thu, 8 May 2003 10:44:04 -0700, Mike Stump <mrs@apple.com> wrote: > > > On Tuesday, May 6, 2003, at 02:02 PM, Jason Merrill wrote: > >> Hmm, I suppose you can assume that $sp is linear. > > > > One can track discontinuities in an along side data structure at the > > discontinuity creation points, and use that to order the comparisons during > > throw time, should we want to. > > Again, this sort of thing sounds like a cure that's worse than the disease. I think our value-functions are not the same. If we were designing a new language, I'd certainly agree with you that exceptions are a good feature. When discussing C on a workstation-class machine, I'd be more likely to agree with you, even though I think adding exceptions to C is antithetical of that language's key design goals. When discussing C for embedded systems, though, I just can't see it. I fully concede that my scheme is less beautiful -- unless you see beauty in the number of bytes saved. I think what really happened here was that the pthreads designers wanted to add pthread_atexit -- and then got carried away. (In fact, so far as I can tell, a careful reading of http://www.unix.org/single_unix_specification/ would suggest that: pthread_cleanup_push (f, a); goto l; pthread_cleanup_pop (1); l: is well-defined, and does not result in the cleanup being executed. Presumably, this should be undefined behavior, as it does not work at all with the sample implementation in the specification. The question of whether pthread_cleanup_push should create a new scope is also important, at least in C99 and C++: is int i; pthread_cleanup_push (f, a); int i; valid, or not, or is this unspecified?) Also, doesn't the execute argument to pthread_cleanup_pop mean that try/finally isn't the right construct? I would think that the EH version of: pthread_cleanup_push (f, a); g (); pthread_cleanup_pop (x); would be: try { g(); } catch (...) { f(a); throw; } if (x) f(a); -- Mark Mitchell <mark@codesourcery.com> CodeSourcery, LLC ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-08 18:40 ` Mark Mitchell @ 2003-05-08 19:06 ` Alexandre Oliva 2003-05-08 19:47 ` Mark Mitchell 2003-05-08 19:37 ` Jason Merrill 1 sibling, 1 reply; 52+ messages in thread From: Alexandre Oliva @ 2003-05-08 19:06 UTC (permalink / raw) To: Mark Mitchell; +Cc: Jason Merrill, Mike Stump, gcc On May 8, 2003, Mark Mitchell <mark@codesourcery.com> wrote: > Also, doesn't the execute argument to pthread_cleanup_pop mean that > try/finally isn't the right construct? > pthread_cleanup_push (f, a); > g (); > pthread_cleanup_pop (x); > would be: > try { > g(); > } catch (...) { > f(a); > throw; > } > if (x) f(a); Err... You're not using try/finally above, and you're not necessarily using the values of f and a that were passed to pthread_cleanup_push. // expanded from pthread_cleanup_push if (1) { void (*__pthr_saved_f)(void *) = (f); void *__pthr_saved_a = (a); bool __pthr_execute = true; try { ; // end of pthread_cleanup_push g (); // expanded from pthread_cleanup_pop __pthr_execute = x; } finally { if (x) __pthr_saved_f(__pthr_saved_a); } } else ; // end of pthread_cleanup_pop it's too bad we can't use the cleaner do/while(0) approach for this, because otherwise we'd change the meaning of break :-( Fortunately a dangling else does almost as well to eat the `;' after pthread_cleanup_pop. This still leaves us with an empty statement after try, but that's not much of a problem. It's not like this is so important, either... Since pthread_cleanup_push and pop are even documented to introduce nesting levels and all, nobody should expect them to expand to a single statement anyway. But still, we need a scope for the temporaries, so we might as well go ahead and make them have block begin/end properties. -- Alexandre Oliva Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/ Red Hat GCC Developer aoliva@{redhat.com, gcc.gnu.org} CS PhD student at IC-Unicamp oliva@{lsd.ic.unicamp.br, gnu.org} Free Software Evangelist Professional serial bug killer ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-08 19:06 ` Alexandre Oliva @ 2003-05-08 19:47 ` Mark Mitchell 2003-05-08 20:19 ` Alexandre Oliva ` (2 more replies) 0 siblings, 3 replies; 52+ messages in thread From: Mark Mitchell @ 2003-05-08 19:47 UTC (permalink / raw) To: Alexandre Oliva; +Cc: Jason Merrill, Mike Stump, gcc > Err... You're not using try/finally above, That was my point: try/finally isn't really the ideal construct. Your version does work, of course -- as does my try/catch expression of the idea, modulo your comments below. > and you're not necessarily > using the values of f and a that were passed to pthread_cleanup_push. This was a mistake, thanks. You're right that the values need to be saved, of course. I agree that all of this is parenthetical; the key question is whether C needs to have EH constructs or not, not which particular constructs they are. Let's just drop that train of thought; it's not going to be productive. I was just musing. It would be nice, though, if the "goto" issue got back to the right people; that should definitely be specified. In the same light, the behavior of "break" and "continue" should be specified; those are also ways of exiting the scope. Undefined behavior might be the right answer. Running the cleanup might not be a good idea; the argument to pthread_cleanup_pop means that the designers thought that sometimes you don't want to run the cleanup. (It's not really like a C++ destructor.) Maybe jumping out of the scope should just be ill-formed, no diagnostic required. I'm not sure, but this isn't the right forum to decide anyhow; I'd just like for the POSIX people to know about the issue. -- Mark Mitchell <mark@codesourcery.com> CodeSourcery, LLC ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-08 19:47 ` Mark Mitchell @ 2003-05-08 20:19 ` Alexandre Oliva 2003-05-08 21:18 ` Jason Merrill 2003-05-09 19:41 ` Kai Henningsen 2 siblings, 0 replies; 52+ messages in thread From: Alexandre Oliva @ 2003-05-08 20:19 UTC (permalink / raw) To: Mark Mitchell; +Cc: Jason Merrill, Mike Stump, gcc On May 8, 2003, Mark Mitchell <mark@codesourcery.com> wrote: >> Err... You're not using try/finally above, > That was my point: try/finally isn't really the ideal construct. Why not? See, the finally case doesn't have the rethrow. It comes automatically from the semantics of finally. This is the right semantics for cleanups. catch(...) doesn't get it right. I do agree that the fact that the pthread cleanup is conditional in the non-unwinding case makes it unsuitable for direct representation as either a cleanup or a finally. You need the conditional in either case. -- Alexandre Oliva Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/ Red Hat GCC Developer aoliva@{redhat.com, gcc.gnu.org} CS PhD student at IC-Unicamp oliva@{lsd.ic.unicamp.br, gnu.org} Free Software Evangelist Professional serial bug killer ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-08 19:47 ` Mark Mitchell 2003-05-08 20:19 ` Alexandre Oliva @ 2003-05-08 21:18 ` Jason Merrill 2003-05-13 21:10 ` Mark Mitchell 2003-05-09 19:41 ` Kai Henningsen 2 siblings, 1 reply; 52+ messages in thread From: Jason Merrill @ 2003-05-08 21:18 UTC (permalink / raw) To: Mark Mitchell; +Cc: Alexandre Oliva, Mike Stump, gcc, Jason Merrill On 08 May 2003 12:47:09 -0700, Mark Mitchell <mark@codesourcery.com> wrote: > I agree that all of this is parenthetical; the key question is whether C > needs to have EH constructs or not, not which particular constructs they > are. I think it does. If we want to be able to interleave pthread cleanups from C and C++ exception handling, then the C code needs to interface with the EH runtime somehow; the obvious way to accomplish this is to use EH for cleanups in threaded C code. For a target that uses sjlj exceptions, this can have exactly the same overhead as the old mechanism. For a target that uses unwind tables, the normal case should be slightly faster than in the old mechanism, since we don't need to call the pthread library to register the cleanup. Code size should be similar. The main overhead is the unwind tables, which just take up disk space unless they're needed. And there's more and more precedent for always emitting unwind tables (ia64, x86-64). I don't see any compelling reason to consider inventing a new mechanism. Jason ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-08 21:18 ` Jason Merrill @ 2003-05-13 21:10 ` Mark Mitchell 2003-05-13 21:25 ` Richard Henderson ` (2 more replies) 0 siblings, 3 replies; 52+ messages in thread From: Mark Mitchell @ 2003-05-13 21:10 UTC (permalink / raw) To: Jason Merrill; +Cc: Alexandre Oliva, Mike Stump, gcc On Thu, 2003-05-08 at 14:16, Jason Merrill wrote: > On 08 May 2003 12:47:09 -0700, Mark Mitchell <mark@codesourcery.com> wrote: > > > I agree that all of this is parenthetical; the key question is whether C > > needs to have EH constructs or not, not which particular constructs they > > are. > > I think it does. If we want to be able to interleave pthread cleanups from > C and C++ exception handling, then the C code needs to interface with the > EH runtime somehow; the obvious way to accomplish this is to use EH for > cleanups in threaded C code. > > For a target that uses sjlj exceptions, this can have exactly the same > overhead as the old mechanism. I owe you an answer on this thread; I apologize for the slow reply. I don't really understand how the SJLJ trick you're describing works, but I am happy to believe you if you are convinced that it does. I'm surprised that there's not a setjmp every time you use pthread_cleanup_push, but it's great if that's not true, and your claim obviously invalidates my performance complaint. I'm still concerned in that doing this to C means that there is no going back -- if something like my alternate-entry-point idea turns out to make sense for some platform there's no way to implement it because people will now be using try/finally all through their code. I'd also still prefer to see a solution that was maximally circumspect; rather than approach this from a "what is the most elegant language design?" point of view, I'd prefer a "what is the absolute minimal feature needed to implement this POSIX requirement?" point of view. That leads me towards __builtin_pthread_cleanup_push. For now, I'd much rather we just do as little as possible in the compiler, and I'd also rather that we encourage people who really want exceptions to use a language that has them. We do ourselves a disservice if we implicitly perpetuate the myth that using the C subset of C++ is somehow worse than just using "straight" C. In any case, there are some semantics to be defined; if a cleanup throws an exception, what happens? (You can't call std::terminate in a pure C program.) Yours, -- Mark Mitchell CodeSourcery, LLC mark@codesourcery.com ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-13 21:10 ` Mark Mitchell @ 2003-05-13 21:25 ` Richard Henderson 2003-05-13 21:41 ` Mark Mitchell 2003-05-13 21:31 ` Gabriel Dos Reis 2003-05-15 17:00 ` Jason Merrill 2 siblings, 1 reply; 52+ messages in thread From: Richard Henderson @ 2003-05-13 21:25 UTC (permalink / raw) To: Mark Mitchell; +Cc: Jason Merrill, Alexandre Oliva, Mike Stump, gcc On Tue, May 13, 2003 at 02:06:50PM -0700, Mark Mitchell wrote: > In any case, there are some semantics to be defined; if a cleanup throws > an exception, what happens? At present, the old exception doesn't get destroyed, and the new exception propagates. I'm not really sure *what* should be said except that it's undefined behaviour. r~ ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-13 21:25 ` Richard Henderson @ 2003-05-13 21:41 ` Mark Mitchell 2003-05-13 22:16 ` Richard Henderson 0 siblings, 1 reply; 52+ messages in thread From: Mark Mitchell @ 2003-05-13 21:41 UTC (permalink / raw) To: Richard Henderson; +Cc: Jason Merrill, Alexandre Oliva, Mike Stump, gcc On Tue, 2003-05-13 at 14:19, Richard Henderson wrote: > On Tue, May 13, 2003 at 02:06:50PM -0700, Mark Mitchell wrote: > > In any case, there are some semantics to be defined; if a cleanup throws > > an exception, what happens? > > At present, the old exception doesn't get destroyed, and > the new exception propagates. I'm not really sure *what* > should be said except that it's undefined behaviour. That's perhaps acceptable; "undefined behavior" is at least an affirmative non-specification. Calling "abort" would seem to be the C-ish equivalent of the C++ std::terminate. -- Mark Mitchell CodeSourcery, LLC mark@codesourcery.com ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-13 21:41 ` Mark Mitchell @ 2003-05-13 22:16 ` Richard Henderson 0 siblings, 0 replies; 52+ messages in thread From: Richard Henderson @ 2003-05-13 22:16 UTC (permalink / raw) To: Mark Mitchell; +Cc: Jason Merrill, Alexandre Oliva, Mike Stump, gcc On Tue, May 13, 2003 at 02:40:17PM -0700, Mark Mitchell wrote: > Calling "abort" would seem to be the C-ish equivalent of the C++ > std::terminate. Yeah. I guess we still have MAY_NOT_THROW regions available with which to attach this call to abort, so it wouldn't be too hard. I dunno if this really warrents such enforcement though... r~ ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-13 21:10 ` Mark Mitchell 2003-05-13 21:25 ` Richard Henderson @ 2003-05-13 21:31 ` Gabriel Dos Reis 2003-05-15 17:00 ` Jason Merrill 2 siblings, 0 replies; 52+ messages in thread From: Gabriel Dos Reis @ 2003-05-13 21:31 UTC (permalink / raw) To: Mark Mitchell; +Cc: Jason Merrill, Alexandre Oliva, Mike Stump, gcc Mark Mitchell <mark@codesourcery.com> writes: [...] | For now, I'd much rather we just do as little as possible in the | compiler, and I'd also rather that we encourage people who really want | exceptions to use a language that has them. We do ourselves a | disservice if we implicitly perpetuate the myth that using the C subset | of C++ is somehow worse than just using "straight" C. I think that the last sentence needs to be emphasized. -- Gaby ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-13 21:10 ` Mark Mitchell 2003-05-13 21:25 ` Richard Henderson 2003-05-13 21:31 ` Gabriel Dos Reis @ 2003-05-15 17:00 ` Jason Merrill 2003-05-15 17:23 ` Mark Mitchell 2 siblings, 1 reply; 52+ messages in thread From: Jason Merrill @ 2003-05-15 17:00 UTC (permalink / raw) To: Mark Mitchell; +Cc: Alexandre Oliva, Mike Stump, gcc On 13 May 2003 14:06:50 -0700, Mark Mitchell <mark@codesourcery.com> wrote: > I'd also still prefer to see a solution that was maximally circumspect; > rather than approach this from a "what is the most elegant language > design?" point of view, I'd prefer a "what is the absolute minimal > feature needed to implement this POSIX requirement?" point of view. > > That leads me towards __builtin_pthread_cleanup_push. I think this is the core of the disagreement, and it seems like a philosophical difference which can't really be addressed with technical arguments. Perhaps this is a matter for the steering committee, after all. Basically, the choice is between a general language extension and a specific compiler hook. > For now, I'd much rather we just do as little as possible in the > compiler, and I'd also rather that we encourage people who really want > exceptions to use a language that has them. We do ourselves a > disservice if we implicitly perpetuate the myth that using the C subset > of C++ is somehow worse than just using "straight" C. But try/finally doesn't provide exceptions. It provides a way of making cleanups explicit, which in turn provides exception safety. People who really want exceptions would still need to use a language that have them. try/finally is a useful construct even in the absence of exceptions; it provides a structured alternative to "goto cleanup_and_return;". > In any case, there are some semantics to be defined; if a cleanup throws > an exception, what happens? (You can't call std::terminate in a pure C > program.) A C++ exception carries a pointer to terminate; we could generalize that. Jason ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-15 17:00 ` Jason Merrill @ 2003-05-15 17:23 ` Mark Mitchell 0 siblings, 0 replies; 52+ messages in thread From: Mark Mitchell @ 2003-05-15 17:23 UTC (permalink / raw) To: Jason Merrill; +Cc: Alexandre Oliva, Mike Stump, gcc On Thu, 2003-05-15 at 09:57, Jason Merrill wrote: > On 13 May 2003 14:06:50 -0700, Mark Mitchell <mark@codesourcery.com> wrote: > > > I'd also still prefer to see a solution that was maximally circumspect; > > rather than approach this from a "what is the most elegant language > > design?" point of view, I'd prefer a "what is the absolute minimal > > feature needed to implement this POSIX requirement?" point of view. > > > > That leads me towards __builtin_pthread_cleanup_push. > > I think this is the core of the disagreement, and it seems like a > philosophical difference which can't really be addressed with technical > arguments. Perhaps this is a matter for the steering committee, after all. > > Basically, the choice is between a general language extension and a > specific compiler hook. I agree. I think that are some semi-technical issues involved, but we have resolved many of them, and the core policy decision seems to be more important than the remaining ones. -- Mark Mitchell CodeSourcery, LLC mark@codesourcery.com ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-08 19:47 ` Mark Mitchell 2003-05-08 20:19 ` Alexandre Oliva 2003-05-08 21:18 ` Jason Merrill @ 2003-05-09 19:41 ` Kai Henningsen 2 siblings, 0 replies; 52+ messages in thread From: Kai Henningsen @ 2003-05-09 19:41 UTC (permalink / raw) To: gcc mark@codesourcery.com (Mark Mitchell) wrote on 08.05.03 in <1052423229.3329.125.camel@minax.codesourcery.com>: > I'm not sure, but this isn't the right forum to decide anyhow; I'd just > like for the POSIX people to know about the issue. Then you might want to contact austin-group-l@opengroup.org - that's the relevant mailing list for discussing this stuff. The Austin Group created both POSIX 2003 and TC1 for that. (And the Single Unix spec V3 aka #define _XOPEN_SOURCE 600 - it's all one text these days.) Or you can use the "Send in a Defect Report" link on the online version at http://unix-systems.org/single_unix_specification/. I think they're about to start work on TC2, so now would be the right moment to bring it up (and possibly the general "what does this mean for C++" question). Subscription to that list is open to everyone, and every subscriber has access to all the drafts. See http://www.opengroup.org/austin/lists.html. MfG Kai ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-08 18:40 ` Mark Mitchell 2003-05-08 19:06 ` Alexandre Oliva @ 2003-05-08 19:37 ` Jason Merrill 1 sibling, 0 replies; 52+ messages in thread From: Jason Merrill @ 2003-05-08 19:37 UTC (permalink / raw) To: Mark Mitchell; +Cc: Mike Stump, gcc, Jason Merrill On 08 May 2003 11:40:21 -0700, Mark Mitchell <mark@codesourcery.com> wrote: > If we were designing a new language, I'd certainly agree with you that > exceptions are a good feature. When discussing C on a workstation-class > machine, I'd be more likely to agree with you, even though I think > adding exceptions to C is antithetical of that language's key design > goals. > > When discussing C for embedded systems, though, I just can't see it. I > fully concede that my scheme is less beautiful -- unless you see beauty > in the number of bytes saved. I argued in my last reply that sjlj EH can have the same cost as the existing pthread cleanup mechanism. Do you disagree? > I think what really happened here was that the pthreads designers wanted > to add pthread_atexit -- and then got carried away. I think they wanted exactly what they wrote. atexit isn't useful for cleanups of a fixed duration. > (In fact, so far as I can tell, a careful reading of > > http://www.unix.org/single_unix_specification/ > > would suggest that: > > pthread_cleanup_push (f, a); > goto l; > pthread_cleanup_pop (1); > l: > > is well-defined, and does not result in the cleanup being executed. > Presumably, this should be undefined behavior, as it does not work at > all with the sample implementation in the specification. Agreed. > The question of whether pthread_cleanup_push should create a new scope > is also important, at least in C99 and C++: is > > int i; > pthread_cleanup_push (f, a); > int i; > > valid, or not, or is this unspecified?) I'd say unspecified or valid. The spec talks about implementation as macros containing { and }. > Also, doesn't the execute argument to pthread_cleanup_pop mean that > try/finally isn't the right construct? > > I would think that the EH version of: > > pthread_cleanup_push (f, a); > g (); > pthread_cleanup_pop (x); > > would be: > > try { > g(); > } catch (...) { > f(a); > throw; > } > if (x) f(a); Hard to do that with macros; you need to store the push args into temporary variables. You'd need to do something like { void (*_f)(void *) = f; void *_a = a; try { g(); } catch (...) { _f (_a); throw; } if (x) _f (_a); } but nobody's advocating adding catch to C, are they? Besides, catch/rethrow is more expensive than running a cleanup. A try/finally implementation would look like { void (*_f)(void *) = f; void *_a = a; int _x = 1; try { g (); _x = x; } finally { if (_x) _f (_a); } } An implementation using C++ destructors would work similarly: struct cleanup { void (*_f)(void *); void *_a; bool _x; cleanup (void (*fn)(void *), void *arg): _f (fn), _a (arg), _x (true) {} ~cleanup () { if (_x) _f(_a); } }; ... { cleanup c (f, a); g (); c._x = x; } Or, using attribute (cleanup): struct cleanup { void (*_f)(void *); void *_a; int _x; }; void cleanup_dtor (struct cleanup *p) { if (p->_x) (p->_f)(p->_a); } ... { struct cleanup c __attribute ((__cleanup (cleanup_dtor))) = { f, a, 1 }; g (); c._x = x; } Any of these would do the job. All of them involve adding EH to C. I think that try/finally is the most elegant way to do that. Jason ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally [not found] ` <1052245742.2583.315.camel@doubledemon.codesourcery.com> [not found] ` <wvlissnc2e3.fsf@prospero.boston.redhat.com> @ 2003-05-07 0:14 ` Richard Henderson 2003-05-07 2:32 ` Mark Mitchell 1 sibling, 1 reply; 52+ messages in thread From: Richard Henderson @ 2003-05-07 0:14 UTC (permalink / raw) To: Mark Mitchell; +Cc: gcc On Tue, May 06, 2003 at 11:29:01AM -0700, Mark Mitchell wrote: > I think RTH accepts the attribute solution as well. He would prefer > try/finally, as I would prefer no extension, but I think we are both > willing to accept the attribute. To some extent I kind-of like the attribute solution on its own. It provides much more structured access to cleanups than the arbitrary block of code that __finally allows. I'm not sure I want to explain to users that jumping out of the __finally block (via goto/break/return) will lead to undefined results. It's less difficult to explain that using longjmp out of a function (under certain conditions) is undefined. > In fact, that solution delivers maximum performance: > > (1) C functions do not need to have handler code inserted. This is false. Handler code gets inserted with the attribute too. > (2) You do not have to transfer control from the EH mechanism to the > stack frame of the caller in order to perform the cleanups. This is false as well. Indeed, I'd expect the most common case would be for the cleanup function to be expanded inline, and reference data cached in registers in the function. > The try/finally solution cannot be implemented with this same > performance; it will, in fact, exact a performance price, in terms of > both code space and the speed at which cleanups are run, on all > systems. On systems with setjmp/longjmp exceptions, both costs will be > very high indeed. No, the overhead is identical. r~ ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-07 0:14 ` Richard Henderson @ 2003-05-07 2:32 ` Mark Mitchell 0 siblings, 0 replies; 52+ messages in thread From: Mark Mitchell @ 2003-05-07 2:32 UTC (permalink / raw) To: Richard Henderson; +Cc: gcc On Tue, 2003-05-06 at 17:11, Richard Henderson wrote: > On Tue, May 06, 2003 at 11:29:01AM -0700, Mark Mitchell wrote: > > I think RTH accepts the attribute solution as well. He would prefer > > try/finally, as I would prefer no extension, but I think we are both > > willing to accept the attribute. > > To some extent I kind-of like the attribute solution on its own. > It provides much more structured access to cleanups than the > arbitrary block of code that __finally allows. > > I'm not sure I want to explain to users that jumping out of the > __finally block (via goto/break/return) will lead to undefined > results. It's less difficult to explain that using longjmp out > of a function (under certain conditions) is undefined. > > > In fact, that solution delivers maximum performance: > > > > (1) C functions do not need to have handler code inserted. > > This is false. Handler code gets inserted with the attribute too. I wasn't talking about the attribute solution in this context. -- Mark Mitchell CodeSourcery, LLC mark@codesourcery.com ^ permalink raw reply [flat|nested] 52+ messages in thread
* __attribute__((cleanup(function)) versus try/finally @ 2003-05-06 19:56 Jason Merrill 2003-05-08 11:59 ` Gabriel Dos Reis 2003-05-08 18:30 ` Mike Stump 0 siblings, 2 replies; 52+ messages in thread From: Jason Merrill @ 2003-05-06 19:56 UTC (permalink / raw) To: gcc [-- Attachment #1: Type: text/plain, Size: 162 bytes --] This discussion started on the steering committee list, but we agreed that it didn't belong there, so I'm forwarding my and Mark's mail to start the discussion. [-- Attachment #2.1: Type: text/plain, Size: 286 bytes --] Subject: Topics Content-length: 249 Topics: Re: __attribute__((cleanup(function)) versus try/finally Re: __attribute__((cleanup(function)) versus try/finally Re: __attribute__((cleanup(function)) versus try/finally Re: __attribute__((cleanup(function)) versus try/finally [-- Attachment #2.2: Type: text/plain, Size: 3705 bytes --] Date: Tue, 06 May 2003 12:50:25 -0400 From: Jason Merrill <jason@redhat.com> Subject: Re: __attribute__((cleanup(function)) versus try/finally Message-ID: <wvlwuh4aujy.fsf@prospero.boston.redhat.com> References: <Pine.BSF.4.55.0305061457450.57349@acrux.dbai.tuwien.ac.at> MIME-Version: 1.0 Content-length: 3393 On Tue, 6 May 2003 15:20:59 +0200 (CEST), Gerald Pfeifer wrote: > For those that didn't follow gcc-patches, there has been strong > disagreement on how to implement exception handling in C for some > time now: > > o RTH (and others) are strongly in favor of try/finally, which is > implemented by several others compilers. Myself among them. try/finally is well defined, and already implemented in other languages and other C compilers. IMO the explicit syntax is in keeping with the spirit of C. If we have any exception handling support whatsoever in C, it should be try/finally. And we've (for some definition of we) always intended to have some EH in C someday. Now that we're trying to integrate pthreads with EH, it's time. > o Mark (and others) are against adding try/finally and favor adding > a different extension: __attribute__((cleanup(function)) which is > "lighter" in a sense. I agree with Alex's comments on this approach; it's trying to introduce the C++ object model into C, which seems like rather a backwards way to approach exception cleanliness. FWIW, here's a post to the glibc list from someone who worked on threading in Tru64, the closest thing to a prior implementation. http://sources.redhat.com/ml/libc-alpha/1999-08/msg00038.html Here's the beginning of the try/finally thread: http://gcc.gnu.org/ml/gcc-patches/2002-11/threads.html#00239 Which includes the message Michael mentions: http://gcc.gnu.org/ml/gcc-patches/2002-11/msg00451.html To sum up, the objections to try/finally amounted to: 1) -fexceptions overhead On any modern OS, the overhead is only on disk unless EH constructs are actually used. The unwind tables are only loaded if an exception is thrown. By contrast, registering pthread cleanups to work with the longjmp_unwind solution involves a setjmp, which needs to run whether or not you throw an exception. 2) implementing something before standardization That's why the patch doesn't create "try" and "finally" keywords, but rather "__try" and "__finally". Though I can't imagine any similar construct having different semantics. 3) poorly defined semantics Nonsense. As I wrote early in the thread: The code in the finally block is run on exit from the try block, except that exiting a try block with a corresponding finally block via longjmp or computed goto has undefined behavior. It's simple, it's straightforward, it shares implementation with the Java frontend. There's tons of prior art. 4) it's the wrong choice Other proposed solutions were: adding destructors to C (i.e. attribute cleanup), Again, I don't want to get into object lifetime stuff in C. try/catch instead C++ doesn't have try/finally because it has destructors. C doesn't need catch for pthreads, but we could implement it later if we want full EH in C. specialized pthread primitive builtins ...which would be modelled internally with TRY_FINALLY_EXPR. I could accept this, but I'd rather provide the more general facility and let the pthreads library worry about pthreads semantics. longjmp_unwind ...which has now been implemented, though I don't think the pthread library uses it yet. IMO none of these are nearly as clean in design as try/finally. Any one of them will be more of a maintenance headache. Jason [-- Attachment #2.3: Type: text/plain, Size: 2160 bytes --] Date: 06 May 2003 11:29:01 -0700 From: Mark Mitchell <mark@codesourcery.com> Subject: Re: __attribute__((cleanup(function)) versus try/finally Message-Id: <1052245742.2583.315.camel@doubledemon.codesourcery.com> References: <Pine.BSF.4.55.0305061457450.57349@acrux.dbai.tuwien.ac.at> MIME-Version: 1.0 Content-length: 1836 On Tue, 2003-05-06 at 06:20, Gerald Pfeifer wrote: > Michael Matz asked that the SC addresses this issue, and I'm forwarding > his message below. I have also suggested to provide more detailed > technical arguments which I'll forward as well. > > For those that didn't follow gcc-patches, there has been strong > disagreement on how to implement exception handling in C for some > time now: > > o RTH (and others) are strongly in favor of try/finally, which is > implemented by several others compilers. > > o Mark (and others) are against adding try/finally and favor adding > a different extension: __attribute__((cleanup(function)) which is > "lighter" in a sense. I think RTH accepts the attribute solution as well. He would prefer try/finally, as I would prefer no extension, but I think we are both willing to accept the attribute. A key point (which seems to be missed by most people in this dicussion) is that you do not need a language extension to get the correct behavior. You simply need to have the exception-handling mechanism aware of the C cleanup stack. In fact, that solution delivers maximum performance: (1) C functions do not need to have handler code inserted. (2) You do not have to transfer control from the EH mechanism to the stack frame of the caller in order to perform the cleanups. The __attribute__ solution can be implemented with the same optimal performance, but that does not seem to be the way in which people intend to implement it. The try/finally solution cannot be implemented with this same performance; it will, in fact, exact a performance price, in terms of both code space and the speed at which cleanups are run, on all systems. On systems with setjmp/longjmp exceptions, both costs will be very high indeed. -- Mark Mitchell CodeSourcery, LLC mark@codesourcery.com [-- Attachment #2.4: Type: text/plain, Size: 2498 bytes --] Date: Tue, 06 May 2003 15:15:48 -0400 From: Jason Merrill <jason@redhat.com> To: Mark Mitchell <mark@codesourcery.com> Subject: Re: __attribute__((cleanup(function)) versus try/finally Message-ID: <wvlissnc2e3.fsf@prospero.boston.redhat.com> References: <Pine.BSF.4.55.0305061457450.57349@acrux.dbai.tuwien.ac.at> <1052245742.2583.315.camel@doubledemon.codesourcery.com> MIME-Version: 1.0 Content-length: 2086 On 06 May 2003 11:29:01 -0700, Mark Mitchell <mark@codesourcery.com> wrote: > A key point (which seems to be missed by most people in this dicussion) > is that you do not need a language extension to get the correct behavior. > > You simply need to have the exception-handling mechanism aware of the C > cleanup stack. That would be an extension too, wouldn't it? In any case, how are you thinking to do this? You've mentioned such a thing before, but I haven't noticed an implementation sketch. > In fact, that solution delivers maximum performance: > > (1) C functions do not need to have handler code inserted. > > (2) You do not have to transfer control from the EH mechanism to the > stack frame of the caller in order to perform the cleanups. > > The __attribute__ solution can be implemented with the same optimal > performance, but that does not seem to be the way in which people intend > to implement it. > The try/finally solution cannot be implemented with this same > performance; it will, in fact, exact a performance price, in terms of > both code space and the speed at which cleanups are run, on all > systems. On systems with setjmp/longjmp exceptions, both costs will be > very high indeed. Hmm. Are you talking about representing cleanups in the LSDA via a function pointer and a CFA offset for the argument object? That way you still need unwind info and PC range tables, but you don't put any code into the function itself. This strategy was discussed at the ABI meetings; I think Intel was advocating it. We all agreed that it was a valid approach, but most of us thought that having the cleanups inline offered more optimization opportunities (code motion into the landing pad, jumping between cleanups, inlining destructors, not forcing the object into the stack). It might make sense to do this for C functions, though. It's somewhat more complicated to do this sort of thing with try/finally, since it allows an arbitrary block of code, not just a call, but the GOTO_SUBROUTINE_EXPR expansion of TRY_FINALLY_EXPR is a very similar idea. Jason [-- Attachment #2.5: Type: text/plain, Size: 3013 bytes --] Date: 06 May 2003 12:38:09 -0700 From: Mark Mitchell <mark@codesourcery.com> To: Jason Merrill <jason@redhat.com> Subject: Re: __attribute__((cleanup(function)) versus try/finally Message-Id: <1052249890.31850.338.camel@doubledemon.codesourcery.com> References: <Pine.BSF.4.55.0305061457450.57349@acrux.dbai.tuwien.ac.at> <1052245742.2583.315.camel@doubledemon.codesourcery.com> <wvlissnc2e3.fsf@prospero.boston.redhat.com> MIME-Version: 1.0 Content-length: 2546 > > You simply need to have the exception-handling mechanism aware of the C > > cleanup stack. > > That would be an extension too, wouldn't it? Yes -- but on the library side, not on the compiler side. The library's going to have extensions no matter what -- this whole pthread cancellation strategy is an extension. > In any case, how are you thinking to do this? You've mentioned such a > thing before, but I haven't noticed an implementation sketch. I did on the gcc list, but it got lost in the noise, I think. The strategy is: (1) Have pthread_cleanup_push include the current $sp in the cleanup record. Otherwise, use the same data structures currently used by glibc's pthread_cleanup_push. (2) When an exception is thrown: - Figure out where the next handler/cleanup will be. (By hypothesis, this is not going to be in C code, because we don't have try/finally in C.) - If unwinding the stack to that destination will result in $sp be older than the $sp recorded in the cleanup at the top of the C cleanup stack, run C cleanups until that is no longer true. - Transfer control to the handler as is done now. > > The try/finally solution cannot be implemented with this same > > performance; it will, in fact, exact a performance price, in terms of > > both code space and the speed at which cleanups are run, on all > > systems. On systems with setjmp/longjmp exceptions, both costs will be > > very high indeed. > > Hmm. Are you talking about representing cleanups in the LSDA via a > function pointer and a CFA offset for the argument object? That way you > still need unwind info and PC range tables, but you don't put any code into > the function itself. I'm not as sophisticated as you about this; I don't actually know what all the EH implementation details are. With the scheme above, you do still need PC range tables and (some?) unwind information, but you don't put any code into the function. I keep mumbling that I think you might be able to avoid some of the unwind information for C, but I've never done what it would take to prove or disprove that assertion. The key point is that you don't need any handler code in the function. The observation behind this is that pthread cleanups -- unlike C++ catch clauses -- do not need to execute in the frame of the function that pushed them. They just need to execute while the stack is still there, in case the "arg" to the function directly or indirectly references stuff on the stack. -- Mark Mitchell CodeSourcery, LLC mark@codesourcery.com ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-06 19:56 Jason Merrill @ 2003-05-08 11:59 ` Gabriel Dos Reis 2003-05-08 15:02 ` Jason Merrill 2003-05-08 18:30 ` Mike Stump 1 sibling, 1 reply; 52+ messages in thread From: Gabriel Dos Reis @ 2003-05-08 11:59 UTC (permalink / raw) To: Jason Merrill; +Cc: gcc Jason Merrill <jason@redhat.com> writes: [...] | > o Mark (and others) are against adding try/finally and favor adding | > a different extension: __attribute__((cleanup(function)) which is | > "lighter" in a sense. | | I agree with Alex's comments on this approach; it's trying to introduce the | C++ object model into C, which seems like rather a backwards way to | approach exception cleanliness. Well, whatever is put in C will (implementation-wise speaking) end up in C++. Therefore if you try to put try/finally in C then you've got to think about how it is suposed to work with C++. And if there is an existing or close to existing mechanism in C++ to achieve those effects then I think it makes sense to write out the C++ approach and try to see which bits can be safely added to C. There is nothing backward in that approach. Rather, it looks rather smooth. In the past kbunch ox extensions have been added to C without thinking about how they would intereact with the rest of the langage and the rest of C++. I believe that is clearly a bogus way to extend C. -- Gaby ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-08 11:59 ` Gabriel Dos Reis @ 2003-05-08 15:02 ` Jason Merrill 0 siblings, 0 replies; 52+ messages in thread From: Jason Merrill @ 2003-05-08 15:02 UTC (permalink / raw) To: Gabriel Dos Reis; +Cc: gcc On 08 May 2003 13:58:54 +0200, Gabriel Dos Reis <gdr@integrable-solutions.net> wrote: > Jason Merrill <jason@redhat.com> writes: > > [...] > > | > o Mark (and others) are against adding try/finally and favor adding > | > a different extension: __attribute__((cleanup(function)) which is > | > "lighter" in a sense. > | > | I agree with Alex's comments on this approach; it's trying to introduce the > | C++ object model into C, which seems like rather a backwards way to > | approach exception cleanliness. > > Well, whatever is put in C will (implementation-wise speaking) end up > in C++. Therefore if you try to put try/finally in C then you've got to > think about how it is suposed to work with C++. Indeed, that's why Aldy's patch added __finally to C++ as well. We did think about how it would work. It works just like it does in Java--there, that was easy. Specifically, a try-block can have both catch and __finally clauses; the __finally must come at the end, and the construct is equivalent to two separate try blocks, with the try/catch inside the try/__finally. > And if there is an existing or close to existing mechanism in C++ to > achieve those effects then I think it makes sense to write out the C++ > approach and try to see which bits can be safely added to C. There is > nothing backward in that approach. Rather, it looks rather smooth. I'm sympathetic to this approach, but the fundamental difference between C and C++ (at least originally) is that C is a procedural abstraction language, and C++ is an object-oriented language. It makes sense to tie cleanups to objects in an object-oriented language; it makes sense to write them explicitly in a procedural language. > In the past a bunch of extensions have been added to C without thinking > about how they would intereact with the rest of the langage and the rest > of C++. I believe that is clearly a bogus way to extend C. That's not the case here. try/finally has already been implemented many times. The semantics are well understood. Jason ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-06 19:56 Jason Merrill 2003-05-08 11:59 ` Gabriel Dos Reis @ 2003-05-08 18:30 ` Mike Stump 2003-05-08 20:49 ` Richard Henderson 1 sibling, 1 reply; 52+ messages in thread From: Mike Stump @ 2003-05-08 18:30 UTC (permalink / raw) To: Jason Merrill; +Cc: gcc On Tuesday, May 6, 2003, at 12:54 PM, Jason Merrill wrote: >> o RTH (and others) are strongly in favor of try/finally, which is >> implemented by several others compilers. > > Myself among them. try/finally is well defined, and already > implemented in > other languages and other C compilers. IMO the explicit syntax is in > keeping with the spirit of C. If we have any exception handling > support > whatsoever in C, it should be try/finally. And we've (for some > definition > of we) always intended to have some EH in C someday. Now that we're > trying > to integrate pthreads with EH, it's time. try/finally I think is a reasonable approach. If table size is a big issue, we can have C default to sjlj EH (lower cost in non-EH code), and integrate in handling for sjlj exceptions into the dwarf EH system. It might be possible to bracket the C code with a single dummy region that just grabs the top element of the sjlj EH stack and throws it, so that non-gcc unwinders can unwind and throw through and into the C code while still being ABI compatible. ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-08 18:30 ` Mike Stump @ 2003-05-08 20:49 ` Richard Henderson 2003-05-08 22:29 ` Mike Stump 0 siblings, 1 reply; 52+ messages in thread From: Richard Henderson @ 2003-05-08 20:49 UTC (permalink / raw) To: Mike Stump; +Cc: Jason Merrill, gcc On Thu, May 08, 2003 at 11:29:50AM -0700, Mike Stump wrote: > If table size is a big issue, we can have C default to sjlj EH (lower > cost in non-EH code), and integrate in handling for sjlj exceptions > into the dwarf EH system. Lets not, please. This is much harder than you realize, and involves a siginificant performance impact to dwarf-only EH. I *did* investigate this once upon a time, when rewriting the exception handling code the last go-round. r~ ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-08 20:49 ` Richard Henderson @ 2003-05-08 22:29 ` Mike Stump 2003-05-13 0:07 ` Geoff Keating 0 siblings, 1 reply; 52+ messages in thread From: Mike Stump @ 2003-05-08 22:29 UTC (permalink / raw) To: Richard Henderson; +Cc: Jason Merrill, gcc On Thursday, May 8, 2003, at 01:46 PM, Richard Henderson wrote: > On Thu, May 08, 2003 at 11:29:50AM -0700, Mike Stump wrote: >> If table size is a big issue, we can have C default to sjlj EH (lower >> cost in non-EH code), and integrate in handling for sjlj exceptions >> into the dwarf EH system. > > Lets not, please. This is much harder than you realize, and > involves a siginificant performance impact to dwarf-only EH. Ok. I was imagining a scheme that elaborated a failure case (lookup the pc and not find any entries) and just checked the new sp value against sjlh_EH_stack->sp and did the sjlj stack processing if required. Maybe there are other nits that complicate it. ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-08 22:29 ` Mike Stump @ 2003-05-13 0:07 ` Geoff Keating 2003-05-13 21:27 ` Richard Henderson 0 siblings, 1 reply; 52+ messages in thread From: Geoff Keating @ 2003-05-13 0:07 UTC (permalink / raw) To: Mike Stump; +Cc: Jason Merrill, gcc Mike Stump <mrs@apple.com> writes: > On Thursday, May 8, 2003, at 01:46 PM, Richard Henderson wrote: > > On Thu, May 08, 2003 at 11:29:50AM -0700, Mike Stump wrote: > >> If table size is a big issue, we can have C default to sjlj EH (lower > >> cost in non-EH code), and integrate in handling for sjlj exceptions > >> into the dwarf EH system. > > > > Lets not, please. This is much harder than you realize, and > > involves a siginificant performance impact to dwarf-only EH. > > Ok. I was imagining a scheme that elaborated a failure case (lookup > the pc and not find any entries) and just checked the new sp value > against sjlh_EH_stack->sp and did the sjlj stack processing if > required. Maybe there are other nits that complicate it. If table size is an issue, how about we just reduce it? For instance, much of the information in the tables is included in the object code (nearly all of it in the case of routines that don't actually have cleanups). It wouldn't be that hard to write a routine that, given a return address, can determine what registers need to be restored and from where in 90% of the cases by looking at the object code; those routines (in the 90%) can have an abbreviated EH entry that just says "use the object code", and the remaining 10% could have a real EH entry. For powerpc-elf, this could be as simple as this algorithm: 1. Look back in the object code until you see a stack push 2. That stack push creates the initial frame, so you know the size of the frame 2. Look forward from here until you see a branch 3a. For the first store of each callee-saved register at an offset from the stack (maybe with some special code for altivec), restore it from that offset. Now, this doesn't work in every case; routines with a too-large stack frame, or that use alloca, won't work, and you won't want to try this with any routine that's larger than a certain size for efficiency reasons, and there may be other cases. But it does work for the vast majority of routines, and it's easy to check (given some RTL) whether it'll work, and that's enough. For x86, you'll want something a bit more complicated, because you'll want to track push/pop operations, but if you can find the start of the routine, you can follow code flow and assume that the stack depth is constant at any particular point to avoid needing to go around loops (like the Java verifier). -- - Geoffrey Keating <geoffk@geoffk.org> ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-13 0:07 ` Geoff Keating @ 2003-05-13 21:27 ` Richard Henderson 2003-05-14 1:14 ` Geoff Keating 0 siblings, 1 reply; 52+ messages in thread From: Richard Henderson @ 2003-05-13 21:27 UTC (permalink / raw) To: Geoff Keating; +Cc: Mike Stump, Jason Merrill, gcc On Mon, May 12, 2003 at 05:07:36PM -0700, Geoff Keating wrote: > For instance, much of the information in the tables is included in the > object code (nearly all of it in the case of routines that don't > actually have cleanups). It wouldn't be that hard to write a routine > that, given a return address, can determine what registers need to be > restored and from where in 90% of the cases by looking at the object > code; those routines (in the 90%) can have an abbreviated EH entry > that just says "use the object code", and the remaining 10% could have > a real EH entry. If you have an entry at all, it means you know the extent of the function being described. So you know where the entry point is. So no searching for that. You'd just read forward from the start. However, if you make the prologue regular enough that code reading is going to work, you're talking about *maybe* 2 bytes per saved register in the EH information, at which point I disbelieve that we're saving enough data space to make this worthwhile. r~ ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-13 21:27 ` Richard Henderson @ 2003-05-14 1:14 ` Geoff Keating 2003-05-14 7:41 ` Richard Henderson 0 siblings, 1 reply; 52+ messages in thread From: Geoff Keating @ 2003-05-14 1:14 UTC (permalink / raw) To: rth; +Cc: mrs, jason, gcc > X-Original-To: geoffk@foam.wonderslug.com > Date: Tue, 13 May 2003 14:24:26 -0700 > From: Richard Henderson <rth@redhat.com> > Cc: Mike Stump <mrs@apple.com>, Jason Merrill <jason@redhat.com>, > gcc@gcc.gnu.org > Mail-Followup-To: Richard Henderson <rth@redhat.com>, > Geoff Keating <geoffk@geoffk.org>, Mike Stump <mrs@apple.com>, > Jason Merrill <jason@redhat.com>, gcc@gcc.gnu.org > Content-Disposition: inline > User-Agent: Mutt/1.4i > X-OriginalArrivalTime: 13 May 2003 21:28:01.0403 (UTC) FILETIME=[880084B0:01C31996] > > On Mon, May 12, 2003 at 05:07:36PM -0700, Geoff Keating wrote: > > For instance, much of the information in the tables is included in the > > object code (nearly all of it in the case of routines that don't > > actually have cleanups). It wouldn't be that hard to write a routine > > that, given a return address, can determine what registers need to be > > restored and from where in 90% of the cases by looking at the object > > code; those routines (in the 90%) can have an abbreviated EH entry > > that just says "use the object code", and the remaining 10% could have > > a real EH entry. > > If you have an entry at all, it means you know the extent of the > function being described. So you know where the entry point is. > So no searching for that. You'd just read forward from the start. > > However, if you make the prologue regular enough that code reading > is going to work, you're talking about *maybe* 2 bytes per saved > register in the EH information, at which point I disbelieve that > we're saving enough data space to make this worthwhile. I was thinking that what you'd do is simply block out large regions of the program with "if you want EH information in here, go look at the object code", so entries would be combined: more space saving, but you do have to search backwards. I wasn't thinking of changing the prologue at all; the plan would be to make the object-code reader sufficiently robust that it can handle most routines, and to include a check for whether this particular routine can be handled by the object-code reader. The reader would do things like skip over opcodes that it didn't understand. -- - Geoffrey Keating <geoffk@geoffk.org> ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-14 1:14 ` Geoff Keating @ 2003-05-14 7:41 ` Richard Henderson 2003-05-14 21:11 ` Geoff Keating 0 siblings, 1 reply; 52+ messages in thread From: Richard Henderson @ 2003-05-14 7:41 UTC (permalink / raw) To: Geoff Keating; +Cc: mrs, jason, gcc On Tue, May 13, 2003 at 06:14:35PM -0700, Geoff Keating wrote: > I wasn't thinking of changing the prologue at all; the plan would be > to make the object-code reader sufficiently robust that it can handle > most routines, and to include a check for whether this particular > routine can be handled by the object-code reader. The reader would > do things like skip over opcodes that it didn't understand. I don't like this at all. There's no way we can make this *that* robust. You need to have prologues in a canonical form, no shrink-wrapping, no complicated block reordering, etc. r~ ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-14 7:41 ` Richard Henderson @ 2003-05-14 21:11 ` Geoff Keating 2003-05-14 22:20 ` Richard Henderson 0 siblings, 1 reply; 52+ messages in thread From: Geoff Keating @ 2003-05-14 21:11 UTC (permalink / raw) To: rth; +Cc: mrs, jason, gcc > X-Original-To: geoffk@foam.wonderslug.com > Date: Wed, 14 May 2003 00:39:01 -0700 > From: Richard Henderson <rth@redhat.com> > Cc: mrs@apple.com, jason@redhat.com, gcc@gcc.gnu.org > Mail-Followup-To: Richard Henderson <rth@redhat.com>, > Geoff Keating <geoffk@geoffk.org>, mrs@apple.com, jason@redhat.com, > gcc@gcc.gnu.org > Content-Disposition: inline > User-Agent: Mutt/1.4i > X-OriginalArrivalTime: 14 May 2003 07:41:37.0074 (UTC) FILETIME=[3FDA1920:01C319EC] > > On Tue, May 13, 2003 at 06:14:35PM -0700, Geoff Keating wrote: > > I wasn't thinking of changing the prologue at all; the plan would be > > to make the object-code reader sufficiently robust that it can handle > > most routines, and to include a check for whether this particular > > routine can be handled by the object-code reader. The reader would > > do things like skip over opcodes that it didn't understand. > > I don't like this at all. There's no way we can make > this *that* robust. You need to have prologues in a > canonical form, no shrink-wrapping, no complicated block > reordering, etc. But that's the truly neat part of the plan, you don't need to make it robust. All you need is to be able to look at RTL and determine whether the object-code reader will be successful in deducing the unwind information; if it would get it wrong, you just output explicit unwind information. -- - Geoffrey Keating <geoffk@geoffk.org> ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally 2003-05-14 21:11 ` Geoff Keating @ 2003-05-14 22:20 ` Richard Henderson 0 siblings, 0 replies; 52+ messages in thread From: Richard Henderson @ 2003-05-14 22:20 UTC (permalink / raw) To: Geoff Keating; +Cc: mrs, jason, gcc On Wed, May 14, 2003 at 02:11:24PM -0700, Geoff Keating wrote: > But that's the truly neat part of the plan, you don't need to make it > robust. All you need is to be able to look at RTL and determine > whether the object-code reader will be successful in deducing the > unwind information; if it would get it wrong, you just output explicit > unwind information. Oh, right. You've got to maintain N+1 versions (rtl, plus N target assemblies) of the same heuristics that (1) operate on different source languages and (2) must be kept in exact sync lest we get incorrect results. That sounds completely unmaintainable. Lets just stick with dwarf2 unwind information, shall we? r~ ^ permalink raw reply [flat|nested] 52+ messages in thread
end of thread, other threads:[~2003-05-15 17:23 UTC | newest] Thread overview: 52+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2003-05-13 21:33 __attribute__((cleanup(function)) versus try/finally Richard Kenner 2003-05-13 22:11 ` Richard Henderson -- strict thread matches above, loose matches on Subject: below -- 2003-05-09 9:54 Ranjit Mathew 2003-05-09 10:16 ` Andrew Haley 2003-05-09 12:08 ` Fergus Henderson 2003-05-09 12:49 ` Jamie Lokier 2003-05-09 9:23 Ranjit Mathew 2003-05-09 9:31 ` Andrew Haley 2003-05-08 7:49 Ranjit Mathew 2003-05-08 21:21 ` Richard Henderson 2003-05-07 10:18 Ranjit Mathew 2003-05-07 13:54 ` Jason Merrill 2003-05-07 18:23 ` Richard Henderson 2003-05-08 18:02 ` Mike Stump [not found] <Pine.BSF.4.55.0305061457450.57349@acrux.dbai.tuwien.ac.at> [not found] ` <1052245742.2583.315.camel@doubledemon.codesourcery.com> [not found] ` <wvlissnc2e3.fsf@prospero.boston.redhat.com> [not found] ` <1052249890.31850.338.camel@doubledemon.codesourcery.com> 2003-05-06 21:04 ` Jason Merrill 2003-05-06 21:24 ` Mark Mitchell 2003-05-07 21:21 ` Jason Merrill 2003-05-07 22:18 ` Mark Mitchell 2003-05-07 23:01 ` Jason Merrill 2003-05-08 12:05 ` Gabriel Dos Reis 2003-05-09 5:46 ` Kai Henningsen 2003-05-06 21:52 ` Anthony Green 2003-05-08 17:44 ` Mike Stump 2003-05-08 17:45 ` Jason Merrill 2003-05-08 18:40 ` Mark Mitchell 2003-05-08 19:06 ` Alexandre Oliva 2003-05-08 19:47 ` Mark Mitchell 2003-05-08 20:19 ` Alexandre Oliva 2003-05-08 21:18 ` Jason Merrill 2003-05-13 21:10 ` Mark Mitchell 2003-05-13 21:25 ` Richard Henderson 2003-05-13 21:41 ` Mark Mitchell 2003-05-13 22:16 ` Richard Henderson 2003-05-13 21:31 ` Gabriel Dos Reis 2003-05-15 17:00 ` Jason Merrill 2003-05-15 17:23 ` Mark Mitchell 2003-05-09 19:41 ` Kai Henningsen 2003-05-08 19:37 ` Jason Merrill 2003-05-07 0:14 ` Richard Henderson 2003-05-07 2:32 ` Mark Mitchell 2003-05-06 19:56 Jason Merrill 2003-05-08 11:59 ` Gabriel Dos Reis 2003-05-08 15:02 ` Jason Merrill 2003-05-08 18:30 ` Mike Stump 2003-05-08 20:49 ` Richard Henderson 2003-05-08 22:29 ` Mike Stump 2003-05-13 0:07 ` Geoff Keating 2003-05-13 21:27 ` Richard Henderson 2003-05-14 1:14 ` Geoff Keating 2003-05-14 7:41 ` Richard Henderson 2003-05-14 21:11 ` Geoff Keating 2003-05-14 22:20 ` Richard Henderson
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).