Ada Exceptions in Safety Critical Embedded Systems [closed]
Asked Answered
S

2

3

I started learning Ada for its potential use in an embedded device which is safety critical. So far, I'm really liking it. However, in my research on embedded programming, I came across the hot topic of whether to use exception handling in embedded systems. I think I understand why some people seem to avoid it:

Now my question is, Does the Ada language or the GNAT compiler address these concerns? My understanding of safety critical code is that non-deterministic code size and execution time is often not acceptable.

Due Diligence: I am having a bit of trouble finding out exactly how deterministic Ada exceptions can be, but my understanding is their original implementation called for more run-time overhead in exchange for reduced code size impact (above first link mentions Ada explicitly). Beyond the above first link, I have looked into profiles mentioning determinism of code, like the Ravenscar profile and this paper, but nothing seems to mention exception handling determinism. To be fair, I may be looking in the wrong places, as this topic seems quite deep.

Sommersommers answered 2/9, 2018 at 15:38 Comment(10)
When you talk about exceptions handling, I suppose you refer to the use of the keyword exception and raise. Concerning your question 1) can't answer that. Question 2) : for critical embedded system, if you need determinism, proofs, and certification proof/artefacts (e.g. for DO-178 and similar), IMO the best method would be to specify, define implement and test your own error handling mechanism.Soupandfish
@LoneWanderer, yes I was referring to the built in exception and raise system. And implementing my own is a fair point. While I am not averse to this option, I just wanted to make sure I wasn't reinventing the wheel unnecessarily. I'm fairly new to Ada, but exploring the strategies for comphrehensive error handling in C has made me realize how challenging it is. If someone more skilled than me (i.e. the board of people who came up with the Ada standard) already made something that works well, I wanted to make sure I was at least aware of it. :)Sommersommers
This is a poll, not an actual programming question. Please read How to Ask to see which questions are on-topic here.Lindi
@toohonestforthissite This is not a poll, but a question about how Ada compilers implement a specific feature of the language. And about how you can work around a sub-optimal implementation of that feature.Turnage
@JacobSparreAndersen: shrug In that case you could have closed as too broad. Actually both are valid close reasons.Lindi
@toohonestforthissite my apologies, I read the "How to Ask", but I guess the topic still wasn't quite right. Is the second half of the question the source of the problem? Would a better way to phrase it be something like "Is there a standard way to address these problems in embedded systems?" Or should I just leave the second part out entirely?Sommersommers
This question is basically a "survey" type question, which asks how things are specifically implemented in a broad class of compilers, i.e. "Ada or its compilers--tools frequently used in safety critical scenarios like military applications--". Such questions tend to draw multiple answers which basically state the user's experience in the subset that they have experience with. This results in it not being possible to determine an answer, have an answer that covers the entire set, or even if an answer is actually correct. Such questions are normally off-topic as too broad/opinion based.Primula
It's possible that you could re-ask a much more narrow question that gets at the heart of what you are interested in, or focuses on one aspect, or one single compiler.Primula
@Makyen, I definitely see what you mean when you say it attracts answers focused on experiences in a subset. Is the above edit better in terms of not focusing on individual experiences in a broad topic, or would it still attract such answers?Sommersommers
@silentTee If it was that way from the beginning, it would have been significantly better.Unfortunately, there is also a policy that you should not edit a question so as to invalidate answers. This leads to a problem when dealing with a question like this where you've already received multiple significantly different answers. It is hard to narrow the question such that it is a fit for SO, while still not invalidating answers. The other site of that is that users with experience should know that it's better to wait to answer until the question is narrowed/clarified.Primula
T
9

Exceptions are deterministic in Ada. (But some checks which can raise an exception have some freedom. If the compiler can provide a correct answer, it doesn't always have to raise an exception, if an intermediate result is out of bounds for the type in question.)

At least one Ada compiler (GNAT) has a "zero cost" exception implementation. This doesn't make exceptions completely free, but you don't pay a run-time cost until you actually raise an exception. You still pay a cost in terms of code space. How large that cost is depends on the architecture.

I haven't worked on safety critical systems myself, but I know for sure that the run-time used for the software in the Ariane 4 inertial navigation system included exceptions.

If you don't want exceptions, one option is to use SPARK (a language derived from Ada). You can still use any Ada compiler you like, but you use the SPARK tools to prove that the program can't raise any exceptions. You should note that SPARK isn't magic. You have to help the tools, by inserting assertions, which the tools can use as intermediate steps for the proofs.

Turnage answered 2/9, 2018 at 17:16 Comment(5)
I found the documentation describing GNAT's "zero cost" exception implementation, but may I ask where you found out about exceptions being deterministic? Or is that simply due to the "zero cost" nature of the implementation? I'm the voracious learning sort that loves to read about these sort of technical details in my free time... and I may be trying to justify a use case to my management. :PSommersommers
The standard (rm.ada.wtf/12/RM-TOC.html) is very explicit about exactly how exceptions work. There's no space for non-deterministic propagation or handling of exceptions.Turnage
Any scope passed while unwinding an exception will involve finalization of entities declared in that scope. Since finalization may involve deallocation, freeing resources etc. I don’t think it can be called deterministic!Plantar
@SimonWright If that's your definition of non-deterministic, then even leaving a declare block is a non-deterministic operation. We seem to disagree here.Turnage
I think I was using the word in the sense that I understood OP to be using - any language in which there could be several exceptions "extant" and it wasn’t defined which would be handled in some circumstance would be weird indeed. I suppose you could have PE raised during finalization happening as a result of some other exception; I imagine the PE gets propagated ...?Plantar
P
12

There are embedded systems that are safety- or mission-critical, embedded systems that are hard real time, and embedded systems that are both.

Embedded systems that are hard real time may be constrained or not. Colleagues worked on a missile guidance system in the 70s that had about 4 instructions worth of headroom in its main loop! (as you can imagine, it was written in assembler and used a tuned executive, not an RTOS. Exceptions weren't supported). On the other hand, the last one I worked on, on a 1 GHz PowerPC board, had a 2 millisecond deadline for the response to a particular interrupt, and our measured worst case was 1.3 milliseconds (and it was a soft real time requirement anyway, you just didn't have to miss too many in a row).

That system also had safety requirements (I know, I know, safe missile systems, huh) and although we were permitted to use exceptions, an unhandled exception meant that the system had to be shut down, missile in flight or no, resulting in loss of missile. And we were strictly forbidden to say when others => null; to swallow an exception, so any exception we didn't handle would be 'unhandled' and would bounce up to the top level.

The argument is, if an unhandled exception happens, you can no longer know the state of the system, so you can't justify continuing. Of course, the wider safety engineering has to consider what action the overall system should take (for example, perhaps this processor should restart in a recovery mode).

Sometimes people use exceptions as part of their control flow; indeed, for handling random text inputs a commonly used method is, rather than checking for end of file, just carry on until you get an End_Error;

loop
   begin
      --  read input
      --  process input
   exception
      when End_Error => exit;
   end;
end loop;

Jacob's answer discusses using SPARK. You don't have to use SPARK to not handle exceptions, though of course it would be nice to be able to prove to yourself (and your safety auditor!) that there won't be any. Handling exceptions is very tricky, and some RTSs (e.g Cortex GNAT RTS) don't; the configuration pragma

pragma Restrictions (No_Exception_Propagation);

means that exceptions can't be propagated out of the scope where they're raised (the program will crash out with a call to a Last_Chance_Handler).

Propagating exceptions only withon the scope where they're raised isn't, IMO, that useful:

begin
   --  do something
   if some error condition then
      raise Err;
   end if;
   --  do more
exception
   when Err =>
      null;
end;

would be a rather confusing way of avoiding the "do more" code. Better to use a label!

Plantar answered 2/9, 2018 at 18:31 Comment(1)
Re "Sometimes people use exceptions as part of their control flow": Right, https://twitter.com/flibitijibibo/status/1037011978600898560Amino
T
9

Exceptions are deterministic in Ada. (But some checks which can raise an exception have some freedom. If the compiler can provide a correct answer, it doesn't always have to raise an exception, if an intermediate result is out of bounds for the type in question.)

At least one Ada compiler (GNAT) has a "zero cost" exception implementation. This doesn't make exceptions completely free, but you don't pay a run-time cost until you actually raise an exception. You still pay a cost in terms of code space. How large that cost is depends on the architecture.

I haven't worked on safety critical systems myself, but I know for sure that the run-time used for the software in the Ariane 4 inertial navigation system included exceptions.

If you don't want exceptions, one option is to use SPARK (a language derived from Ada). You can still use any Ada compiler you like, but you use the SPARK tools to prove that the program can't raise any exceptions. You should note that SPARK isn't magic. You have to help the tools, by inserting assertions, which the tools can use as intermediate steps for the proofs.

Turnage answered 2/9, 2018 at 17:16 Comment(5)
I found the documentation describing GNAT's "zero cost" exception implementation, but may I ask where you found out about exceptions being deterministic? Or is that simply due to the "zero cost" nature of the implementation? I'm the voracious learning sort that loves to read about these sort of technical details in my free time... and I may be trying to justify a use case to my management. :PSommersommers
The standard (rm.ada.wtf/12/RM-TOC.html) is very explicit about exactly how exceptions work. There's no space for non-deterministic propagation or handling of exceptions.Turnage
Any scope passed while unwinding an exception will involve finalization of entities declared in that scope. Since finalization may involve deallocation, freeing resources etc. I don’t think it can be called deterministic!Plantar
@SimonWright If that's your definition of non-deterministic, then even leaving a declare block is a non-deterministic operation. We seem to disagree here.Turnage
I think I was using the word in the sense that I understood OP to be using - any language in which there could be several exceptions "extant" and it wasn’t defined which would be handled in some circumstance would be weird indeed. I suppose you could have PE raised during finalization happening as a result of some other exception; I imagine the PE gets propagated ...?Plantar

© 2022 - 2024 — McMap. All rights reserved.