Version 1.1 of acs/ac-00219.txt

Unformatted version of acs/ac-00219.txt version 1.1
Other versions for file acs/ac-00219.txt

!standard 11.4.1(13/2)          12-01-06 AC95-00219/00
!class confirmation 11-06-17
!status received no action 11-06-17
!status received 11-04-15
!subject Proposal Ada 2012 concerning Ada.Exceptions.Exception_Infomation
!summary
!appendix

From: Dr. Joachim Schroerr
Sent: Friday, April 15, 2011  4:18 AM

Dears Ladies, Sirs

I would replace 13/2 in

11.4.1 The Package Exceptions

With a note requiring Exception_Information to return a readable call stack,
e.g.

13/2 Exception_Information returns besides implementation-defined information
about the exception occurrence a readable call stack with subprogram and
source-file and line information. The returned string has lower bound 1.

See e.g. Gnat.Traceback.Symbolic.Symbolic_Traceback.

There are Ada95 implementations (Green Hills) and Gnat-Implementations of Ada
2005 around (Mac Os X) that do not support a call stack.

You really miss it during development.

This a in my opinion the single real advantage of Java to have a readable
exception call stack required in the standard.

***************************************************************

From: Georg Bauhaus
Sent: Monday, April 18, 2011 12:18 PM

...
> This a in my opinion the single real advantage of Java to have a readable
> exception call stack required in the standard.

I don't think Java's stacktrace includes calls from within JNI methods?

***************************************************************

From: Florian Weimer
Sent: Monday, April 18, 2011  2:37 PM

Uhm, they do?

***************************************************************

From: Florian Weimer
Sent: Monday, April 18, 2011  2:44 PM

> There are many processors (some of which our compiler targets) for
> which a call stack can't even be unwound without a ton of extra
> information being present in the program.

Agreed.  On the other hand, it might be useful to add implementation advice to
C.7.3 to the effect that in the Unhandled_Exception case, the
Termination_Handler should be called before the stack is unwound. This way, the
programmer is free to use platform-specific stack unwinding information, or to
trigger a crash dump which still reflects the original call stack.

This would be similar to a subset to the functionality provided by
C++'s std::set_unexpected.

***************************************************************

From: Adam Beneschan
Sent: Monday, April 18, 2011  3:42 PM

I don't know what std::set_unexpected does.  My knowledge of C++ is quite
limited.

I think your proposal would be a change in the semantics; thus, it couldn't be
done simply by adding to Implementation Advice.  C.7.3(8) says that the
Termination_Handler is called when a task terminates. 9.3(5) says that a task
terminates when the finalization of the body has been performed.  Suppose task
body A calls procedure B, and B calls C, and C raises an exception that is not
handled anywhere within A or B.  Your proposal seems to suggest that the
Termination_Handler should be called while A, B, and C are still all on the
stack.  But suppose B declares a local variable V that requires a finalization
routine to be performed; the code probably has to return from C before it can
finalize V, especially if the Finalize routine needs to access some of B's local
variables.  Calling the Termination_Handler while C is still on the stack means
that it's called before V is finalized; since the task termination occurs after
V is finalized, this is a significant change in the dynamic semantics.

I suppose it might be possible to cook up a scheme that would allow V (and any
other variables in A or B) to be finalized while C is still on the stack, but it
seems to me this could require a major change in implementations.

There may be other ways to provide the ability to retrieve a stack for an
exception occurrence, or for an unhandled exception occurrence, but I'd be
opposed to *requiring* that the information be available since it could involve
major changes to some Ada implementations.

***************************************************************

From: Florian Weimer
Sent: Monday, April 18, 2011  4:05 PM

>> This would be similar to a subset to the functionality provided by
>> C++'s std::set_unexpected.
>
> I don't know what std::set_unexpected does.  My knowledge of C++ is
> quite limited.

It is called when an unhandled exception is encountered.  The stack is not
unwound, and destructors (finalizers) of on-stack objects are not invoked.

> I think your proposal would be a change in the semantics; thus, it
> couldn't be done simply by adding to Implementation Advice.  C.7.3(8)
> says that the Termination_Handler is called when a task terminates.
> 9.3(5) says that a task terminates when the finalization of the body
> has been performed.

*grrr*  Missed that.

> There may be other ways to provide the ability to retrieve a stack for
> an exception occurrence, or for an unhandled exception occurrence, but
> I'd be opposed to *requiring* that the information be available since
> it could involve major changes to some Ada implementations.

Could you add another type of handler callback?  Do implementations decide if a
handler exists before beginning to unwind the stack in earnest?

I think that in most cases, you want stack traces for unhandled exceptions only,
or cases where you currently write a "when E : others" handler which logs and
swallows the exception, without actually handling it in an exception-specific
manner.  Both could be converted to the new callback.  These are supposed to be
quite rare, so performance of generating the stack trace is not as important as
it would be if stack traces were added to all exceptions.  The question where to
put the (possibly unbounded) stack trace data does not arise, either.

***************************************************************

From: Randy Brukardt
Sent: Monday, April 18, 2011  4:13 PM

...
> There may be other ways to provide the ability to retrieve a stack for
> an exception occurrence, or for an unhandled exception occurrence, but
> I'd be opposed to *requiring* that the information be available since
> it could involve major changes to some Ada implementations.

I agree. IMHO, the only way to provide accurate stack information is for the
implementation to keep a trace of it while running, and this is not free (both
in time and space).

Specifically, Janus/Ada doesn't try to unwind the stack, because the different
calling conventions format the stack in different ways, and assembler code
doesn't have to follow any format at all. So, in Janus/Ada, each task has a
trace call stack that includes subprogram names and call line numbers. This is
pushed/popped on entrance/exit to each subprogram. An exception occurrence
contains a copied snapshot of the top of this this stack (an exception
occurrence is quite large).

Since there is substantial overhead to this information, there is a compiler
switch to turn it off. That eliminates the overhead, but it also means that any
routines compiled that way don't appear in any walkback information. Similarly,
the runtime can be built without the support for these stacks for use on tiny
embedded systems, in which case there is no support at all.

We also use this same mechanism to gather subprogram-based profiling
information.

In any case, requiring implementations to go to these lengths seems wrong; what
makes sense depends on the intended use (embedded vs. hosted), the
characteristics of the target system, and customer needs. In any case, the
Standard cannot reasonably mandate a "good" implementation; that's between
customers and vendors.

***************************************************************

From: Adam Beneschan
Sent: Monday, April 18, 2011  4:22 PM

> > There may be other ways to provide the ability to retrieve a stack
> > for an exception occurrence, or for an unhandled exception
> > occurrence, but I'd be opposed to *requiring* that the information
> > be available since it could involve major changes to some Ada implementations.
>
> Could you add another type of handler callback?  Do implementations
> decide if a handler exists before beginning to unwind the stack in
> earnest?

I'm aware of both implementations that do, and implementations that don't.
However, the implementations that *do* decide if a handler exists probably
wouldn't do what you want if there's a subprogram on a stack that has a handler
like:

   exception
      when others =>
         Some_Cleanup_Routine;
         raise;

And the ones I'm aware of would not be able to distinguish an explicit handler
written in Ada from an implicit one generated by the compiler to finalize local
variables.  And what if an explicit handler like the above didn't always do a
reraise, but did so based on a condition?

I'd assume that in the above case, you'd still want to have the stack trace for
the original exception that caused the exception occurrence.  The stack trace
for the subprogram that calls Some_Cleanup_Routine may not be all that useful.
Or it might.

Anyway, adding a second type of handler callback is one of the possible
solutions I was envisioning.  But even so, it seems challenging to define a
feature in a way that is useful, can be feasibly implemented, and doesn't
require overhead in programs that don't raise any exceptions in implementations
that don't already have overhead.

***************************************************************

From: Randy Brukardt
Sent: Monday, April 18, 2011  5:05 PM

...
> I'm aware of both implementations that do, and implementations that
> don't.  However, the implementations that *do* decide if a handler
> exists probably wouldn't do what you want if there's a subprogram on a
> stack that has a handler like:
>
>    exception
>       when others =>
>          Some_Cleanup_Routine;
>          raise;

We have special handling for reraises specifically to deal with this problem; an
exception occurrence includes copies of parts of both stacks (the original one,
and the last reraise if any). None of this is cheap, and as such, it doesn't
make sense for the Standard to require it.

(And to reply to Florian, I think there are as many ways of identifying
exception handlers as there are compilers, and possibly more than that. :-)
There is little commonality in this area, so we can't really consider rules
based on what some particular implementation can do.)

***************************************************************

From: Jeff Cousins
Sent: Tuesday, April 19, 2011  3:35 AM

Note that if you raise an exception with a user-supplied string then you lose
this implementation-defined information (which in GNAT's case is the useful
package name and line number of the exception) -  see RM 11.4.1 para 10.1/2 (Ada
2005) or 10.1/3 (Ada 2012).  It would have been more useful for debugging to
have allowed both user-supplied string and implementation-defined information.

***************************************************************

From: Randy Brukardt
Sent: Tuesday, April 19, 2011  3:33 PM

I think you are confused. The user-defined string replaces the
implementation-defined Exception_Message information. But it does not replace
the implementation-defined exception occurrence information (that is, the
information provided beyond the exception message and the exception name). This
is the information discussed in 11.4.1(13/2) - this is not the same as the
information disucssed in 11.4.1(10.1/2). Of course, there is no requirement that
there be any such information.

For Janus/Ada, the implementation-defined exception message is empty for most
exceptions, but contains additional information for some of the language-defined
exceptions. In particular, a Constraint_Error caused by a discrete value being
out of range includes the out of range value. If you provide an user-specified
message, this information is replaced and not available.

OTOH, walkback information is part of Exception_Information, and is provided for
all exception occurrence values (unless the value is streamed out; since it
contains pointers to subprogram names that probably aren't the same in another
program, it is stripped at that point).

***************************************************************


Questions? Ask the ACAA Technical Agent