Version 1.10 of ais/ai-00166.txt

Unformatted version of ais/ai-00166.txt version 1.10
Other versions for file ais/ai-00166.txt

!standard C.3.2 (16)          00-04-11 AI95-00166/05
!standard C.3.2 (18)
!class binding interpretation 96-11-16
!status Corrigendum 2000 99-07-27
!status WG9 approved 99-06-12
!status ARG approved (7-0-0) 98-10-09
!status work item (draft by Ted Baker, per action at St. Louis meeting)
!status received 96-11-16
!priority Medium
!difficulty Medium
!qualifier Clarification
!subject Parameterless_Handler values designating default treatment
!summary
When a default treatment is in effect for an interrupt, the value returned by Current_Handler is null. Likewise, the value returned in Old_Handler by the Exchange_Handler procedure is null if it is invoked while the default treatment is in force for the specified interrupt.
Furthermore, the value returned by Current_Handler and in Old_Handler must be null whenever the treatment is not a user-defined handler.
!question
C.3.2(18) says, "The Exchange_Handler procedure operates in the same manner as Attach_Handler with the addition that the value returned in Old_Handler designates the previous treatment for the specified interrupt." This would seem to suggest that if Exchange_Handler is invoked while the default treatment is still in force, the value in Old_Handler can be dereferenced, with the dereference denoting a parameterless protected procedure that can be called to obtain the default treatment. Is this the intent? (No.)
!recommendation
(See summary.)
!wording
C.3.2(16) and C.3.2(18) need to be changed to reflect the summary of this AI. in C.3.2(16): "...If no user-defined handler is attached to the interrupt, Current_Handler returns null. ..." in C.3.2(18): add "If the previous treatment is not a user-defined handler, null is returned."
!discussion
A key fact here is that a "treatment" of an interrupt (whether default or user-defined) is not limited to execution of a handler, and even if the treatment is to call a handler the handler may be something other than a parameterless protected procedure.
There may be external mechanisms (perhaps in hardware or in an operating system) that can mediate the delivery of a signal in a way that is distinct from executing a handler procedure. For example, in the UNIX environment the concept of interrupt corresponds to that of a "signal"; the default treatments for signals include ignoring (discarding) the signal or performing job-control functions including terminating the process (with or without memory dump), stopping the process, and continuing a stopped process. Even with hardware interrupts, the default treatment that is initially in place when a program starts up is unlikely to be calling an Ada protected procedure.
The intent of the International Standard is to allow treatments other than parameterless protected procedures as defaults is expressed clearly in C.3 (5):
Each interrupt has a default treatment which determines the system's response to an occurrence of that interrupt when no user-defined handler is attached. The set of possible default treatments is implementation defined, as is the method (if one exists) for configuring the default treatments for interrupts.
Note that the default treatment of an interrupt is not even required to be static. It is possible that an implementation or underlying operating system may have a mechanism that modifies the default treatment of an interrupt (or signal) while a program is running.
C.3 (29) gives implementation advice as to examples of possible default treatments, but does not limit them:
(1) The default treatment for an interrupt can be to keep the interrupt pending or to deliver it to an implementation-defined handler. Examples of actions that an implementation-defined handler is allowed to perform include aborting the partition, ignoring (i.e., discarding occurrences of) the interrupt, or queuing one or more occurrences of the interrupt for possible later delivery when a user-defined handler is attached to that interrupt.
Moreover, the intent of the ARM is to allow user-specified handlers that are not parameterless protected procedures, as specified in C.3 (26)
Other forms of handlers are allowed to be supported, in which case, the rules of this subclause should be adhered to.
For example, it would be legal for an implementation to define a way to attach an ordinary procedure to an interrupt, or in the case of UNIX signals to attach ordinary procedures of several forms -- one with no parameter, one with a single, signal parameter, one with a signal parameter and a context parameter, etc.
This is emphasized in C.3.1 (19):
Notwithstanding what this subclause says elsewhere, the Attach_Handler and Interrupt_Handler pragmas are allowed to be used for other, implementation defined, forms of interrupt handlers.
and again in C.3.2 (25):
If implementation-defined forms of interrupt handler procedures are supported, such as protected procedures with parameters, then for each such form of a handler, a type analogous to Parameterless_Handler should be specified in a child package of Interrupts, with the same operations as in the predefined package Interrupts.
This means that if an implementation supports handlers or other interrupt treatments (whether default or user-specified) there will be situations in which the semantics of the operations defined in Ada.Interrupts for parameterless protected procedure handlers must be modified to take into account these other forms of treatments or handlers.
If Ada.Interrupts.Current_Handler or Ada.Interrupts.Exchange_Handler is called in a situation where the treatment in force for a given interrupt (whether default or user-specified) does not correspond to any parameterless protected procedure, the operation cannot return a value that designates a callable parameterless protected procedure.
Note that even if we were willing to require an implementation to create a "fake" Ada protected procedure, so as to be able to return a reference to a callable protected procedure, we have situations where the default treatment cannot be simulated by a protected procedure.
The intent of this section was that the value returned by Current_Handler or in Old_Handler may "represent" a handler or other treatment that is not a parameterless protected procedure, e.g., it might be an integer code for a default treatment or the address of some other kind of handler, unchecked-converted to the type Parameterless_Handler. The notion was that such a value might not be usable for calling the handler directly from the application, but could meaningfully and safely be used to restore the old treatment or handler, by passing it back as New_Handler in a call to Exchange_Handler. This provides the capability for a user to safely install a handler, and then later restore the previous treatment, without needing to worry about whether the previous treatment is a parameterless protected procedure.
This intent is reflected in the first sentence of C.3.2 (16), which says Current_Handler returns a value that "represents" the attached handler, rather than "designates". It is unfortunate that the word "designates" was inadvertently substituted in the second sentence, where the case of there being no user-defined handler is discussed.
Original intent aside, the question does raise a valid pragmatic issue. There are situations where it is desirable to allow the "cascading" of handlers, i.e., when a new handler is installed using Exchange_Handler, the new handler may use the previous handler (returned in the Old_Handler parameter) to call the previous hander -- for those situations where the previous handler was a parameterless protected procedure. However, to cascade handlers in this fashion, the application must know that there is a callable handler and the parameter profile of the handler.
It might be nice if there were a "portable" way for an application to determine whether the value returned in Old_Handler or by Current_Handler is one that can be dereferenced to call a parameterless protected procedure, as in the handler-cascading model. The ARM itself does not explicitly specify how this can be determined, but it can be interpreted in a way that may suffice.
C.3.2 (17) does require that the null access value can be used to specify the default treatment for an interrupt:
The Attach_Handler procedure attaches the specified handler to the interrupt, overriding any existing treatment (including a user handler) in effect for that interrupt. If New_Handler is null, the default treatment is restored. ...
This binding interpretation extrapolates from the above to conclude that the value returned by Current_Handler, and the value returned in Old_Handler by Exchange_Handler, must be the null access value whenever the treatment that is in force for the given signal is the default treatment. It further extrapolates to conclude that the null access value must be returned whenever the treatment is not a user-installed handler. It follows that for implementations that support only parameterless protected procedures as handlers, these operations return only the null value and access values that can be used to call a parameterless protected procedure.
This provides a way to safely cascade user-installed handlers, provided the application uses only parameterless procedures as handlers.
This is a compromise. It does not provide the full capability that the original question hoped for; i.e., there is no way to "call" the default treatment. Likewise, if the implementation supports other forms of handlers, and the application uses them, there remains the possibility that the value returned by Current_Handler or in Old_Handler represents a handler that is not a parameterless protected procedure, and so it would be erroneous to call it without parameters. On the other hand, it would still be safe to use Exchange_Handler to restore such a handler.
!corrigendum C.03.02(16)
Replace the paragraph:
The Current_Handler function returns a value that represents the attached handler of the interrupt. If no user-defined handler is attached to the interrupt, Current_Handler returns a value that designates the default treatment; calling Attach_Handler or Exchange_Handler with this value restores the default treatment.
by:
The Current_Handler function returns a value that represents the attached handler of the interrupt. If no user-defined handler is attached to the interrupt, Current_Handler returns null.
!corrigendum C.03.02(18)
Replace the paragraph:
The Exchange_Handler procedure operates in the same manner as Attach_ Handler with the addition that the value returned in Old_Handler designates the previous treatment for the specified interrupt.
by:
The Exchange_Handler procedure operates in the same manner as Attach_ Handler with the addition that the value returned in Old_Handler designates the previous treatment for the specified interrupt. If the previous treatment is not a user-defined handler, null is returned.
!ACATS test
Add a test case to CXC3007 to check that the default treatment returns null.
!appendix

!section C.3.2(18)
!subject Parameterless_Handler values designating default treatment
!reference RM95-C.3.2(18)
!from Norman Cohen
!keywords interrupt handler chaining designate default treatment
!reference 96-5714.a Norman H. Cohen 96-10-2>>
!discussion

C.3.2(18) says, "The Exchange_Handler procedure operates in the same
manner as Attach_Handler with the addition that the value returned in
Old_Handler designates the previous treatment for the specified
interrupt."  This would seem to suggest that if Exchange_Handler is
invoked while the default treatment is still in force, the value in
Old_Handler can be dereferenced, with the dereference denoting a
parameterless protected procedure that can be called to obtain the
default treatment.  Is this the intent?

On the one hand, it is easy to construct a legalistic exegesis (building
on the definition of "designates" in 3.10(1), the ramification of
3.10(13) that an access value said to designate something cannot be the
null access value, and the rules for evaluation of a dereference in
4.1(13)) that says that it must be possible to invoke the default
treatment in this way.  Furthermore, this approach has an important
practical use in allowing different applications to "chain" handlers for
a given interrupt, as explained below.  C.3.2(17) states that a null
value for the New_Handler parameter of Attach_Handler (and, as a
consequence of C.3.2(18), of Exchange_Handler) specifies restoration of
the default treatment; but this does not mean that null is the ONLY
Parameterless_Handler value specifying the default treatment.

On the other hand, since the default treatment in effect when a program
begins execution is not, in general, an Ada protected procedure, it may
be difficult for an implementation to invoke that treatment through a
protected procedure call.  (C.3.2(16), C.3.2(17), and C.3.2(19) all
require the implementation to have some way of restoring the default
treatment, but invoking the default behavior without restoring it might
be more difficult for some implementations.)  Although the word
"designates" in C.3.2(18) suggests that there must be a nonnull
Parameterless_Handler value designating the default treatment for a
given interrupt, this word may have been written casually, without
regard to its full implications, and without  the intention that the
default behavior be invokable through a protected-procedure call.

Chaining is the practice of an application installing a handler for a
interrupt that does whatever processing is required by the application
and then invokes the handler that was in effect for that interrupt
before the application was invoked, thus "passing the interrupt on".
This previous handler might itself be the next link on a chain of
handlers that ends with the system handler.   Presumably, when a handler
is installed for an interrupt before an Ada application is invoked, the
"default treatment" for that interrupt (see C.3(5)) is to invoke that
handler.

Here is an approach by which an application might install a handler for
a timer interrupt that captures the fact that the interrupt has
occurred, then passes the interrupt on to the next handler in the chain:

   package Timer is
      protected Tick_Gate is
         entry Wait_For_Tick;    -- for use by clients
         procedure Report_Tick;  -- for internal use only
      private
         Pending_Ticks: Natural := 0;
      end Tick_Gate;
   end Timer;

   with Ada.Interrupts; use Ada.Interrupts;

   package body Timer  is

      protected body Tick_Gate is

         entry Wait_For_Tick when Pending_Ticks > 0 is
         begin
            Pending_Ticks := Pending_Ticks - 1;
         end Wait_For_Tick;

         procedure Report_Tick is
         begin
            Pending_Ticks := Pending_Ticks + 1;
         end Report_Tick;

      end Tick_Gate;

      Previous_Timer_Interrupt_Handler: Parameterless_Handler;

      protected Timer_Interrupt_Handler is
         procedure Handle;
         pragma Interrupt_Handler (Handle);
      end Timer_Interrupt_Handler;

      protected body Timer_Interrupt_Handler is
         procedure Handle is
         begin
            Tick_Gate.Report_Tick;
            Previous_Timer_Interrupt_Handler.all;
         end Handle;
      end Timer_Interrupt_Handler;

   begin

      Exchange_Handler
         (Old_Handler => Previous_Timer_Interrupt_Handler,
          New_Handler => Timer_Interrupt_Handler.Handle'Access,
          Interrupt   => Timer_Interrupt_ID);

   end Timer_Interrupts;

Note that the questions I have raised with regard to the use of the word
"designates" for the Exchange_Handler procedure in C.3.2(18) apply also
to the use of the word "designates" for the result of the
Current_Handler function in C.3.2(16).  However, the interpretation of
C.3.2(16) is further complicated by term "user-defined handler", which I
take to mean a handler installed during execution of the current active
partition.  (Language designers and application designers have different
views of  who the "user" is!)  Indeed, the Timer_Interrupts package
initialization above would have been more
correctly written as

   Previous_Timer_Interrupt_Handler :=
      Current_Handler (Timer_Interrupt_ID);
   Attach_Handler
      (Timer_Interrupt_Handler.Handle'Access, Timer_Interrupt_ID);

to forestall the possibility of a timer interrupt occurring after the
body of Exchange_Handler had completed, but before the value of
Old_Handler was copied back to Previous_Timer_Interrupt_Handler, leading
to execution of the call

   Previous_Timer_Interrupt_Handler.all;

while Previous_Timer_Interrupt_Handler was still null.

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

!section C.3.2(18)
!subject Parameterless_Handler values designating default treatment
!reference RM95-C.3.2(18)
!reference 96-5714.a Norman H. Cohen 96-10-2
!from Ted Baker
!keywords interrupt handler chaining designate default treatment
!reference 96-5723.a Ted Baker  96-10-13>>
!discussion

| ... This would seem to suggest that if Exchange_Handler is
| invoked while the default treatment is still in force, the value in
| Old_Handler can be dereferenced, with the dereference denoting a
| parameterless protected procedure that can be called to obtain the
| default treatment.  Is this the intent?

That was not exactly the intent.

The intent was to allow something like the UNIX sigaction()
interface, which uses certain "special" values that are not
themselves procedure pointers, to indicate special treatments
(namely, the default treatment and to ignore the signal).

For example, the value -1 might be reserved to indicate
the default treatment.

Thus, the only thing a user can safely do using the value returned
by Exchange_Handler is to pass it back for re-installation later.

Attempting to dereference and directly call this value was not
intended to be safe.

--Ted Baker

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

!section C.3.2(18)
!subject Parameterless_Handler values designating default treatment
!reference RM95-C.3.2(18)
!reference 96-5714.a Norman H. Cohen 96-10-2
!reference 96-5723.a Ted Baker 96-10-13
!keywords interrupt handler chaining designate default treatment
!from Tucker Taft 96-10-14
!reference 1996-5724.a Tucker Taft 1996-10-14>>
!discussion

> | ... This would seem to suggest that if Exchange_Handler is
> | invoked while the default treatment is still in force, the value in
> | Old_Handler can be dereferenced, with the dereference denoting a
> | parameterless protected procedure that can be called to obtain the
> | default treatment.  Is this the intent?
>
> That was not exactly the intent.
>
> The intent was to allow something like the UNIX sigaction()
> interface, which uses certain "special" values that are not
> themselves procedure pointers, to indicate special treatments
> (namely, the default treatment and to ignore the signal).
>
> For example, the value -1 might be reserved to indicate
> the default treatment.

Since "null" is used to indicate a default treatment elsewhere
(RM95-C.3.2(17)), I would certainly presume that one could rely
on "null" being used to represent the default treatment on return
from Exchange_Handler.

> Thus, the only thing a user can safely do using the value returned
> by Exchange_Handler is to pass it back for re-installation later.
>
> Attempting to dereference and directly call this value was not
> intended to be safe.

On the other hand, I would say that comparing it with "null" would
be a safe and reliable way of distinguishing the default treatment
from a "real" handler.

I agree with Norm that the use of the term "designates" is unfortunate
in C.3.2(16,18).  In both cases, it should be explicit that "null"
is used to "represent" the default treatment; there seems no need for
the word "designate" at all.

> --Ted Baker

-Tuck

P.S. Our ada-comment-processing software was temporarily dormant
due to our (finally!) switching over from SunOS to Solaris.  I believe
it is up and running regularly now.  As far as I know, no messages
were lost, just delayed a bit. -T

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

!section C.3.2(18)
!subject Parameterless_Handler values designating default treatment
!reference RM95-C.3.2(18)
!reference 96-5714.a Norman H. Cohen 96-10-2
!reference 96-5723.a Ted Baker 96-10-13
!reference 96-5724.a Tucker Taft 96-10-14
!keywords interrupt handler chaining designate default treatment
!from Ted Baker
!reference 96-5725.a Ted Baker  96-10-14>>
!discussion

| > The intent was to allow something like the UNIX sigaction()
| > interface, which uses certain "special" values that are not
| > themselves procedure pointers, to indicate special treatments
| > (namely, the default treatment and to ignore the signal).

| Since "null" is used to indicate a default treatment elsewhere
| (RM95-C.3.2(17)), I would certainly presume that one could rely
| on "null" being used to represent the default treatment on return
| from Exchange_Handler.

1) You are certainly presuming, if you do that, since
   it is not a stated requirement.

2) An implementation may want to use more than one
   special value, such as to make the UNIX SIG_DFL vs. SIG_IGN
   distinction.

We certainly considered, but did not require, that the operation
return "null" for the default treatment.  Implementing that
requirement would impose an extra layer of mechanism on the
interface.  Our intention was to allow implementors to make it
very "thin", where appropriate.  For example, on a bare machine,
the operation might translate directly to a few machine
instructions that directly modify the interrupt vector; in that
case the default treatment would come back as a (callable)
interrupt handler address.

By the way, the term "default treatment" was intentionally chosen
as compared to "default handler", to avoid implying that the
default treatment be accessible (in the form of a reference to a
user-callable handler).  Thus, for example, the default treatment
might be to simply disable the interrupt (for a direct hardware
implementation) or to ignore the signal (in UNIX) or to kill the
process (in UNIX).

| > Attempting to dereference and directly call this value was not
| > intended to be safe.

| On the other hand, I would say that comparing it with "null" would
| be a safe and reliable way of distinguishing the default treatment
| from a "real" handler.

See above.

--Ted Baker

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

!section C.3.2(18)
!subject Parameterless_Handler values designating default treatment
!reference RM95-C.3.2(18)
!reference 96-5714.a Norman H. Cohen 96-10-2
!reference 96-5723.a Ted Baker 96-10-13
!reference 96-5724.a Tucker Taft 96-10-14
!keywords interrupt handler chaining designate default treatment
!reference 96-5725.a Ted Baker 96-10-14
!reference 1996-5726.a Tucker Taft 1996-10-14>>
!discussion

> | > The intent was to allow something like the UNIX sigaction()
> | > interface, which uses certain "special" values that are not
> | > themselves procedure pointers, to indicate special treatments
> | > (namely, the default treatment and to ignore the signal).
>
> | Since "null" is used to indicate a default treatment elsewhere
> | (RM95-C.3.2(17)), I would certainly presume that one could rely
> | on "null" being used to represent the default treatment on return
> | from Exchange_Handler.
>
> 1) You are certainly presuming, if you do that, since
>    it is not a stated requirement.

It is a stated requirement that "null" be interpreted as the default
treatment when passed in as the New_Handler to Attach_Handler or
Exchange_Handler.  It didn't seem much of a leap to presume that
it would also be the same on return.  Given the confusion, we clearly
need to be more explicit, one way or the other.

> 2) An implementation may want to use more than one
>    special value, such as to make the UNIX SIG_DFL vs. SIG_IGN
>    distinction.

This doesn't make sense to me, since you only have one value in
Attach_Handler/Exchange_Handler on the way in to specify the default
treatment, namely "null."

> We certainly considered, but did not require, that the operation
> return "null" for the default treatment.  Implementing that
> requirement would impose an extra layer of mechanism on the
> interface.  Our intention was to allow implementors to make it
> very "thin", where appropriate.  For example, on a bare machine,
> the operation might translate directly to a few machine
> instructions that directly modify the interrupt vector; in that
> case the default treatment would come back as a (callable)
> interrupt handler address.

I don't see the point of this micro-optimization.  You have to explicitly
check for "null" on the New_Handler.  It seems unwise to return a
value for Old_Handler that could create erroneous situations
just to save a few instructions.  I don't believe that Current_Handler
or Exchange_Handler are that performance sensitive.  Certainly handling
interrupts should be as efficient as possible, but establishing
interrupt handlers is not as common an event (for example, we don't
indicate any interesting metrics are associated with their actions).

> By the way, the term "default treatment" was intentionally chosen
> as compared to "default handler", to avoid implying that the
> default treatment be accessible (in the form of a reference to a
> user-callable handler).  Thus, for example, the default treatment
> might be to simply disable the interrupt (for a direct hardware
> implementation) or to ignore the signal (in UNIX) or to kill the
> process (in UNIX).

All the more reason to use the "null" value to represent it.
If the way to indicate a default treatment is not "null", then
we would need a function to test whether the Parameterless_Handler
value is meaningful.  That seems like overkill.

> | > Attempting to dereference and directly call this value was not
> | > intended to be safe.
>
> | On the other hand, I would say that comparing it with "null" would
> | be a safe and reliable way of distinguishing the default treatment
> | from a "real" handler.
>
> See above.

I can feel an AI in the making...

> --Ted Baker

-Tuck

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

!section C.3.2(18)
!subject Parameterless_Handler values designating default treatment
!reference RM95-C.3.2(18)
!reference 96-5714.a Norman H. Cohen 96-10-2
!reference 96-5723.a Ted Baker 96-10-13
!reference 96-5724.a Tucker Taft 96-10-14
!reference 96-5725.a Ted Baker 96-10-14
!reference 96-5726.a Tucker Taft 1996-10-14
!reference 96-5728.a Ted Baker 1996-10-15
!keywords interrupt handler chaining designate default treatment
!reference 1996-5728.a Tucker Taft 1996-10-15>>
!discussion

> | > By the way, the term "default treatment" was intentionally chosen
> | > as compared to "default handler", to avoid implying that the
> | > default treatment be accessible (in the form of a reference to a
> | > user-callable handler).  Thus, for example, the default treatment
> | > might be to simply disable the interrupt (for a direct hardware
> | > implementation) or to ignore the signal (in UNIX) or to kill the
> | > process (in UNIX).
>
> | All the more reason to use the "null" value to represent it.
> | If the way to indicate a default treatment is not "null", then
> | we would need a function to test whether the Parameterless_Handler
> | value is meaningful.  That seems like overkill.
>
> I think maybe you are over-simplifying the issue.  There is
> information loss here.
>
> How is the implementation going to tell whether it should return
> "null"?  i.e. after the treatment has been changed a few times,
> how does the implementation recognize that the current treatment
> is the "default" one?

With your Unix/Posix example, it seems clear that any treatment which
does not have a user-specified signal handler routine must be
considered "default," and would be returned as "null."

I understand that there is some potential loss in target-specific
functionality, but that will always be the case when you try
to provide a standard package for interfacing to the target.

An implementation could provide a different package, or a child,
which acknowledged the possibility of multiple default treatments,
etc., I just don't think that kind of target-specific functionality
belongs in a standard package.  Otherwise, code that looks like it
ought to be portable from, say, one Posix environment to the next,
is not, because one vendor chose to use "null" to represent the
default treatment, and another didn't.

You could keep things relatively portable if you ensured that
if the Old_Handler were non-null, then it would be legitimate to
call it in a way suggested in Norm's original note.
But returning some special value in Old_Handler that would result
in chaos if it were called seems unnecessarily error prone.

I hope we agree that an AI is needed to resolve this issue...

> --Ted Baker

-Tuck

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

!section C.3.2(18)
!subject Parameterless_Handler values designating default treatment
!reference RM95-C.3.2(18)
!reference 96-5714.a Norman H. Cohen 96-10-2
!reference 96-5723.a Ted Baker 96-10-13
!reference 96-5724.a Tucker Taft 96-10-14
!reference 96-5725.a Ted Baker 96-10-14
!reference 96-5726.a Tucker Taft 1996-10-14
!reference 96-5728.a Ted Baker 1996-10-15
!reference 1996-5728.a Tucker Taft 1996-10-15
!keywords interrupt handler chaining designate default treatment
!reference 96-5730.a Ted Baker  96-10-16>>
!discussion

| I hope we agree that an AI is needed to resolve this issue...

Personally, I would rather leave it implementation-defined.

At least, if an AI is drawn up, I would argue that it should allow
the implementation to choose between two possible outcomes when
one exchanges out the default treatment:

1) The value returned is a legitimate pointer that can be
dereferenced and called by the user in a "cascade" fashion.

2) The value returned is null.

I think option (1) gives the user an important capability for
bare-machine implementations, and option (2) makes more sense for
a UNIX implementation.

If forced to choose between (1) and (2), I'd choose (1)*, since I'd
rather add more overhead and lost capability to the UNIX system
(where performance is already slow and there are other avenues to
get functionality) than to remove the capability of cascading
handlers for the bare-machine case.

*Here, I'm fudging, since I don't believe (1) can actually be
implemented in a UNIX environment.  If asked to implement it, I'd
be forced to do an approximation that would not hold up if
stressed.  It seems the only way to get the default action would
be to install it globally for the process, unmask the signal, have
the process send itself the signal again, and then (if the process
was not killed) reverse the actions.  I guess this could be
wrapped in a protected procedure, modulo the fact that the signal
cannot be blocked during execution of the handler.  The main
problem I see is the dynamic side-effects of mucking with the
signal state; if another signal comes in during the window between
swapping in the default action and swapping back while this
protected procedure is executing, that signal would directly
invoke the default action, rather than the user-specified handler.

--Ted Baker

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

From the minutes of the Henley meeting:

AI-166 Parameterless_Handler values designating default treatment

What is this AI saying?

Apparently Norm wants to tighten the semantics for the default handler.
This is counter to the principle of leaving the semantics vague to permit
implementation flexibility, especially on existing operating systems.  Ted
complicates the situation by pointing out that an operating system can
change the default treatment.

Also, there are some style changes, namely the use of treatment and handler
that is causing confusion; Bob indicates that treatment was added to permit
the ability of the default to change (by the OS).

Erhard summarizes the alternatives (and prefers no. 1):
1. Current and old handler is null for default treatment; this was modified
by Ted to "for any non-user-provided handler/treatment"
2. Current and old handler is not null and callable (by X.all)
3. Current and old handler is not null and may be callable if it is user-
defined handler and not callable if it is default handler/treatment

Bob states that the current statement of the RM permits either 1 or 3 as
defined by the implementation.

Erhard asks for vote, late in the first day, on Alternative 1: 6-3

On the next  day:

Ted convinced himself by the name "Exchange Handler" that the
focus of this operation is handler and not treatments; so that
default treatment is expressed by null for the purposes of the Ada
application and for later exchange (restoration).

The only remaining issue is the possibility of changing the
default treatment from the underlying OS.  After some discussion
of the terms "current", "default" and "current default", it was
decided to stick with "default" with comments that the OS
implementation may change the value of default treatment; "current
default" would only encourage such behavior.

Erhard asks for a revote on Alternative 1:  9-0-0

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


Questions? Ask the ACAA Technical Agent