have a trivial test program that implements one function, INV, which just computes 1/x. Passing 0 for the argument x triggers a zero-division error. When I compile it with ifort (version 2021.3.0), using the flags "/fpe-all:0 /traceback /fp:strict /debug" and run it, I get a traceback like this:
forrtl: error (73): floating divide by zero Image PC Routine Line Source ifort-tst.exe 00007FF7EB0411F0 F_mp_INV 9 f.f ifort-tst.exe 00007FF7EB0410A2 MAIN__ 8 tst.f
In my real application, we call Fortran code from a Python process, using f2py. With a bit of tinkering (had to define macros UPPERCASE_FORTRAN and NO_APPEND_FORTRAN) I was able to compile the same code as a Python module. When I run it from Python, the zero-division causes the program to quit but does not produce the backtrace. If I don't set "/fpe-all:0" the module just returns a NaN instead of aborting, so I know the FPE compiler flags are in effect. I want the program to abort on floating-point exceptions, but I want to see the same type of backtrace that is produced when I run the code as a stand-alone executable.
I suspect that some needed signal handler is not getting registered - with GNU Fortran it's necessary to call a few library initialization functions to make FPE handling work but I was not able to find the equivalent in the Intel Fortran documentation.
My understanding of how this works is that the traceback is generated by a C++ wrapper around a Fortran main program, and if there is no Fortran (or Intel C++) main, then you don't get tracebacks. You CAN call TRACEBACKQQ at any point to get a traceback, and you might investigate whether adding a call to SIGNALQQ, to register your own handler, gives you a place from which to call TRACEBACKQQ.
Your use of /fpe-all is correct in that without this, the setting of FP exception handling is done in the main program only. /fpe-all adds the call to do this in every procedure. But it doesn't help with traceback.
Thanks Steve, this is exactly the kind of info I was looking for.
It seems like a signal handler needs to be set up to trap SIG$FPE.
I followed your suggestion of calling TRACEBACKQQ, this works as expected when I call if from a Fortran main program, but not when I compile the code as a library and call it from Python. It does cause the program to exit, but the traceback just isn't printed. If we can figure out why that's happening, I'll be all set.
On Linux, calling TRACEBACKQQ from an f2py-generated module works - it prints a traceback and aborts. On Windows, it aborts without printing a traceback.
In neither case do I get a traceback on FPE, even if I call SIGNALQQ(SIG$FPE, TRACEBACK) where TRACEBACK is a function that calls TRACEBACKQQ. (The wrapper needed to match expected signature for SIGNALQQ).
I'm afraid my understanding of this part of things is very superficial - not sure I have more I can add. I think TRACEBACKQQ prints to stderr - maybe it can't open that? I suggest you look more carefully at the documentation of TRACEBACKQQ - it has a bunch of stuff about exception pointers.
One small step forward, TRACEBACKQQ noiw works from f2py wrapper on Windows if I include the line
which I had been missing (the code compiles without this, just doesn't print a traceback on Windows). Still haven't gotten this to work from the FPE handler, though.