3

I would like to be able to catch a terminating Fortran runtime errors in a C++ binding. I have a legacy F90 code to bind to and expect all kind of errors e.g. numerical, IO etc.

I managed to handle STOP according to: Intercepting Fortran STOP from C++ and able to throw/catch exception for this case in the C++ code.

I got some understanding 'Signal Handling in Fortran' at https://www.sharcnet.ca/help/images/4/42/Fortran_Signal_Handling.pdf

However I do not manage with this, an example for f90 fortran would be very helpful.

For example trying to open a non existant file in the fortran subroutine would give a runtime error, and the C++ code terminates:

open (unit=13,FILE="fnameBAD",status="old",action="read",position="rewind")

Fortran runtime error: Cannot open file 'fnameBAD': No such file or directory

I would like to be able to catch this and other runtime errors using signals.

levego70
  • 41
  • 3
  • What do you mean by saying `signals`? – Coral Kashri Jun 09 '19 at 20:52
  • signal handling (SIGTERM or SIGINT) – levego70 Jun 09 '19 at 20:53
  • Why don't you just use `try..catch..`? – Coral Kashri Jun 09 '19 at 20:55
  • when the fortran code submits the terminating signal the C++ wrapper terminates immediately (before catch does not catch it). I would need to throw the exception somehow..seems that somehow 'call signal(SIGTERM,myfunction)' could work, where myfunction could throw an exception, but I did not manage with this. – levego70 Jun 09 '19 at 21:07
  • I think this could help you: https://stackoverflow.com/questions/1641182/how-can-i-catch-a-ctrl-c-event – Coral Kashri Jun 09 '19 at 21:18
  • 4
    Fortran has ways to disable those error messages, use the `iostat=` specifier and check its returned value. There is nothing in the Fortran standard that would require the compiler to issue signals. It requires to terminate the program. – Vladimir F Героям слава Jun 10 '19 at 05:40
  • And use tag fortran for all Fortan questions, you also didn't tag just C++11 (or similar). Many other Fortran standard versions can be in a .f90 file, not just Fortran 90. – Vladimir F Героям слава Jun 10 '19 at 07:19
  • Thank you for all the helpful answers. So its seems its best to cleanup the Fortran code (i.e. make ir more robust). I will need to check on Fortran programming pitfalls that cause similar errors, i.e. terminates the execution. If someone can suggest a good link that could be very helpful! – levego70 Jul 06 '19 at 08:28

2 Answers2

2

This won't work, at least for GFortran. When then OPEN statement fails, the GFortran runtime library will shut itself down, and only finally is the signal generated. So by the time you can catch the signal in the signal handler, libgfortran has already shut itself down (including closing all open files).

The solution, as Vladimir F says in a comment, is to catch the error in the OPEN statement with the iostat= specifier.

janneb
  • 36,249
  • 2
  • 81
  • 97
0

I've implemented something like that for unittesting C-bindings for a Fortran code from C/C++ to catch abort calls using setjmp and longjmp (essentially the same as an answer in the already linked question):

#include <setjmp.h>
#include <signal.h>

jmp_buf jmp_env;

void on_sigabrt(int signum)
{
    (void) signum; // silence "unused parameter" warning
    longjmp(jmp_env, 1);
}

void func()
{
    if (setjmp(jmp_env) == 0) {
        signal(SIGABRT, &on_sigabrt);
        /* YOUR CALLS HERE */
    } else {
        /* ERROR HANDLING GOES HERE */
    }
}

The problem @janneb already described remains: Even while longjmp should restore the stack to the point of the setjmp, it does not guarantee that all internal state in the Fortran runtime library is restored.

In fact, both books Modern Fortran: Style and Usage (rule 182) and The Fortran 2003 Handbook (15.6.4) mention that Fortran code should not be wrapped in between setjmp and longjmp.

On the other hand, there are compiler vendors which explicitly provide setjmp/longjmp wrappers (Oracle for example), as well as several projects with a similar focus:

That being said, it is likely a better (and more portable) approach to use proper error handling using the iostat attribute whenever possible, as others already commented.

dev-zero
  • 81
  • 1
  • 9