Catching fortran runtime errors and signals in C++ binding - c++

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.

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.

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:
funwind
zsvjmp
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.

Related

Redirect c++ crash to stderr

Considering a small program like this :
int main()
{
freopen("./stdout.log", "w", stdout);
freopen("./stderr.log", "w", stderr);
int a = 1 / 0;
}
and considering my program is ran by a third party software where I can't change neither how the program is launched nor the environment.
How to properly catch the Floating point exception (core dumped) message issued by the division by zero and any other messages that would still be printed on the tty ?
I've tried to search SO for similar answer but I might be just typing the wrong keywords as it seems a common practice.
Matthieu Brucher's comment is correct:
You need to catch the signals, which is platform dependent.
From the text of the message, I infer that you may be running on a Linux platform. If so, you can catch the SIGFPE signal.
#include <stdexcept>
#include <signal.h>
// compile with -fnon-call-exceptions (for gcc)
signal(SIGFPE, [](int signum) { throw std::logic_error("FPE"); });
The linked answer has some C++ niceties such as using a std::shared_ptr for RAII management of the signal handler and mentions compiler flags needed for gcc to make that work.
The Linux Programming Interface book also has a pure-C example.
In Windows, you can use Structured Exception Handling (SEH) and the concept is similar (although the functions you need to call are not).
Note that in either case you're relying on platform-specific behavior not specified by C++ (division by zero is undefined behavior) so obviously this will not result in portable code.

How to catch C++ exceptions in C? [duplicate]

I am developing C++ component dll that can be used by C or C++ applications.
The exposed dll functions are as follows
#include <tchar.h>
#ifdef IMPORT
#define DLL __declspec(dllimport)
#else
#define DLL __declspec(dllexport)
#endif
extern "C" {
DLL bool __cdecl Init();
DLL bool __cdecl Foo(const TCHAR*);
DLL bool __cdecl Release();
}
the internal implementation of these functions are C++ classes which are not exposed, I assume using this style the dll can be used either in C or C++ apps.
The problem is I do not handle any type of c++ exception (i.e. bad_alloc) and I left this stuff to the caller (the higher layer).
After much debate with my colleagues that I should catch all the exceptions and return error code or at least false because in case of C application it can not handle C++ exceptions? is that true? and what I should do in general? is there a rule of thumb for handling exeptions if you are developing component that will be used by other system.
C doesn't have exceptions, therefore in general you should catch all exception and return an error code and/or provide a function that returns the information about the last error.
If this is Windows using MSVC then yes you can catch exceptions in C but you can't catch them that well. C++ exceptions are fed through the OS ABI's Structured Exception Handling mechanism, and Microsoft have a __try, __except, __finally C extension to handle OS structured exceptions. Note that these include access violations, divide-by-zero, etc. that you'd normally want to terminate your program and log a bug report. You can identify C++ exceptions by code 0xE04D5343 (4D 53 43 = "MSC") and throw the rest on.
That all said, you probably don't want to be throwing exceptions across a DLL boundary, and certainly not if you're only exposing a C API.
As a general rule, you should never allow C++ exceptions to propagate beyond a module's boundary. This is because the C++ standard does not specify how exception propagation has to be implemented, and as such this is compiler (and compiler flags) and operating system dependent. You cannot guarantee that the code calling your module will be compiled with the same compiler with the same compiler flags as your module. In fact, as you're demonstrating with this question is that you cannot guarantee that code calling your module will be written in the same language.
For more details, please refer to Item 62 in C++ Coding Standards by Sutter and Alexandrescu.
Ok, since it was asked for:
C++ example code:
#include <typeinfo>
#include <exception>
extern "C" {
void sethandler(void (*func)(void)) { std::set_terminate(func); }
int throwingFunc(int arg) {
if (arg == 0)
throw std::bad_cast();
return (arg - 1);
}
}
C example code:
#include <stdio.h>
extern int throwingFunc(int arg);
extern void sethandler(void (*func)(void));
void myhandler(void)
{
printf("handler called - must've been some exception ?!\n");
}
int main(int argc, char **argv)
{
sethandler(myhandler);
printf("throwingFunc(1) == %d\n", throwingFunc(1));
printf("throwingFunc(-1) == %d\n", throwingFunc(-1));
printf("throwingFunc(0) == %d\n", throwingFunc(0));
return 0;
}
When I compile these two, link them together and run this (Ubuntu 10.04, gcc 4.4.5, x64), I get:
$ ./xx
throwingFunc(1) == 0
throwingFunc(-1) == -2
handler called - must've been some exception ?!
Aborted
So while you can catch exceptions from C, that's hardly sufficient - because C++ runtime behaviour after std::terminate() is undefined, and because the handler gets no status information whatsoever (to distiguish exception types and/or sources). The handler cannot clean up anything.
Btw, I've deliberately chosen std::bad_cast() as exception type in this example. This is because throwing that illustrates a difference in behaviour between std::set_unexpected() and std::set_terminate() - the unexpected handler will get called for all non std::bad_* exceptions, while in order to catch standard exceptions, a terminate handler is required ... see the dilemma ? The harness is too wide to be of practical use :(
Only propagate exceptions to the caller if the caller is designed to handle them. I guess in your case terminate() will be called immediately once any exception escapes C++ code because from the point of C++ runtime that exception has not been handled.
The same situation arises in COM servers design - the clients can be in whatever language/technology. The rul is that no exceptions should escape COM server methods - all exceptions must be caught and translated in HRESULT and (optionally) IErrorInfo. You should do similarly in your situations.
In case C code is sandwiched between two layers of C++ code propagating exceptions to C code is still a very bad idea.

Qt error handling for fortran subroutines

I have a Qt GUI project that calls a fortran subroutine from a C++ function. This fortran subroutine reads some data from a text file. But whenever the fortran code fails (e.g. bad integer in item list etc), the GUI window automatically closes.
Is there a way to prevent it from closing if an error occures?
I tried using try-catch blocks like this
try
{
// fortran function call
test_();
}
catch(...)
{
qDebug()<<"Error";
}
but it didn't work. Throwing exceptions with the throw statement does work however.
I also tried to subclass QApplication class and reimplement the notify() function:
bool SafeApp::notify(QObject* obj,QEvent* event)
{
try
{
return QApplication::notify(obj,event);
}
catch(std::exception& e)
{
return false;
}
}
The code compiles and runs fine, but it still crashes after calling the fortran function.
Fortran does not have exceptions, so the Fortran function you're calling is not throwing anything that C++ can catch.
OTOH, in Fortran the default behavior for errors such as I/O errors is to stop the program. The GFortran runtime library uses the libc exit() or abort() functions for this, depending on what kind of error is encountered.
What you might be able to do, is to add IOSTAT= and/or IOMSG= specifiers to the Fortran I/O statements. In that case errors will cause a nonzero iostat and some message in the string pointed to by IOMSG rather than stopping the program.

C++ exception handling in C codes

When we write a program in C, it is possible that we will call some libraries that were wrote in C++ but had a C interface. Then it may happen that when we call these libraries, a C++ exception will occur. So my question is how we can handle this situation. I am more interested in this problem from a C++ developer's perspective. Suppose I am developing a C++ library that will be invoked by a C program, should I stop using exception and instead return error codes? Another situation is that if I have already a fully developed C++ library that uses exception, how can I transfer this library in a quick way that will only use error returning method?
You have to catch all exceptions on the C++ side and convert them to appropriate error returns in C, which may include specific error codes where appropriate. This doesn't mean that you stop using exceptions — you can still use them in C++ — but you can't expose them to C, they become an implementation detail.
A typical wrapper can be structured as follows:
// thingy-wrapper.h, typically included from C code:
#ifdef __cplusplus
extern "C" {
#endif
// create a typedef visible to C that doesn't expose the layout of
// the implementation.
typedef void *thingy_t;
// wrapper for std::string Thingy::get_name()
char *thingy_get_name(thingy_t t);
#ifdef __cplusplus
}
#endif
// thingy-wrapper.cpp, implements the wrapper, compiled with C++:
#include <thingy-wrapper.h>
#include <thingy.hpp> // declares Thingy class
char *thingy_get_name(thingy_t t_)
{
try {
Thingy& t = *static_cast<Thingy*>(t_);
std::string name = t.get_name();
return strdup(name.c_str());
}
catch(...) {
return NULL;
}
}
In this simple example, the caller of thingy_get_name can detect that an error occurred, but cannot find out the details of the error. A more realistic example would catch specific exceptions, and set a last_error variable to an error code or message before returning NULL. ... would only be caught as a last resort, and would set last_error to a generic UNKNOWN_ERROR value. A separate API for querying the last error, such as thingy_last_error(), would be available for the more careful callers of thingy_get_name().
The separation between error and non-error results enables code that doesn't care about the cause of errors to simply check if it received NULL, while allowing more conscientious code to properly propagate or report the error. If your library is multi-threaded, make sure that last_error uses thread-local storage.
Then it may happen that when we call these libraries, a C++ exception will occur. So my question is how we can handle this situation.
The C code cannot handle this situation. C code cannot deal with C++ exceptions.
Suppose I am developing a C++ library that will be invoked by a C program, should I stop using exception and instead return error codes?
No. If you want the C++ library to be consumed by C++ code you should use native C++ error handling. Which means exceptions.
However, the interface that you expose to the C code must not throw exceptions. Typically this means writing an adaptor layer that catches exceptions raised by the C++ library, and converts them into error codes to be consumed by the C code.
Another situation is that if I have already a fully developed C++ library that uses exception, how can I transfer this library in a quick way that will only use error returning method?
There's really no shortcut here. You have to write the adaptor that converts C++ exceptions into C error codes. You'll be writing an adaptor anyway if you want the library to expose interfaces for both C and C++ consumers. So the aspect of error handling is just another thing to take care of with this adaptor.
Exception are not caught in C so if you want to catch them then in your C code or your C++ code you have to write the wrappers very carefully.
Also make sure that in your C++ functions you have your functions declared as:
extern "C"
You may also check How to mix C and C++

Throwing an exception in C++ in a C callback, possibly crossing over dynamic library boundary... is it safe?

I'm using libjpeg right now to save JPEG images. If there is an error, libjpeg's default behavior is to call exit(), which I want to avoid since it's not a fatal error for my program. libjpeg allows you to use your own error manager, and mandates that if you use your own error_exit() function (which calls exit() by default) you must not return control to the caller. libjpeg suggests using setjmp.h to meet this requirement and not exit() the program.
However, I am writing a C++ program, and I have access to exceptions. This question's answer states it's safe (as in well-defined behavior) to throw an exception from the callback. But it doesn't mention dynamic libraries, and there's a general rule of thumb that you don't throw exceptions across dynamic library boundaries.
Here's an example:
#include <iostream>
#include <jpeglib.h>
#include <cstdio>
#include <stdexcept>
static void handleLibJpegFatalError(j_common_ptr cinfo)
{
(*cinfo->err->output_message)(cinfo);
throw std::runtime_error("error in libjpeg, check stderr");
}
int main()
{
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE* file = std::fopen("out.jpeg", "wb"); // assume this doesn't fail for this example
try
{
cinfo.err = jpeg_std_error(&jerr);
jerr.error_exit = handleLibJpegFatalError;
// let's say this triggers a fatal error in libjpeg and handleLibJpegFatalError() is called
// by libjpeg
jpeg_create_compress(&cinfo);
}
catch (...)
{
std::cerr << "Error saving the JPEG!\n";
}
jpeg_destroy_compress(&cinfo);
std::fclose(file);
}
What I would like to know is: can I throw an exception from this callback, and catch it back in my application, even if libjpeg is compiled as a dynamic library? libjpeg may be a static or dynamic library, and if it's a dynamic library it may possibly be built with a different compiler. However, the code that throws and catches the exception will certainly be in the same compilation unit. Is the above code safe?
FYI, I'm developing for OS X and Windows (and keeping the future of a Linux possibility in mind), so I'm more interested in if this is known to be well defined behavior in general, and not for a specific platform/compiler.
The other answer applies here. Nothing will get trashed when unwinding the stack. It doesn't even matter if the library uses some crazy calling convention internally, as long as it doesn't specifically mess with your C++ implementation's exception handling structures (which it wont as a C program). No C++ implementation that I know of finds the catch block by popping off stack frames (that would make optimization a nightmare), they all maintain internal structures for exception handling. As long as a call lower down in the call chain doesn't mess with those structures, stack unwinding will work perfectly fine for all of your personal code. Now, in general, it's quite possible that this would leave a library with a messed up internal state as you never return execution to the library for cleanup, but in the case of your error callback, libjpeg expects for control flow to not return and has presumably already cleaned up after itself.
In this case, I would go for it. In general, I would only throw fatal exceptions from a C callback.
Hope that helped.
It's not safe. Depending on how the relevant non-C++ library code was compiled, the necessary unwind tables may not exist. This is just a practical reason why it might fail; the conceptual reason is that it's simply undefined behavior.
You should follow the documentation and use setjmp/longjmp to get just outside the call to libjpeg code, then throw an exception immediately in the if (setjmp(...)) { ... } body if you want to use exceptions.
As discussed in other answers, it ought to be safe as long as you are in control of all the modules and they will be built by the same toolchain (inc. statically linking).
But I want to add a caveat here that some toolchains require this support to be turned on, since libjpeg's functions are marked extern "C". By default, Visual Studio assumes that such functions will not propagate exceptions.
If you don't turn this on, expect much pain. I spent hours on a testcase almost identical to yours before I realised this. 😃