Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Error catching in a DLL

larryscheier
Beginner
1,021 Views
I inherited a program with thousands of fortran subroutines, some of which can be nested 10 deep from the main calling routine. This program was originally a Fortran DOS exe which I converted to an fortran DLL. The problem is this: If any of the routines finds an error in the user input, a ShowSevereError routine is called to dump an error to a reporting file, then a STOP was issued. Obviously, I took out the STOP, but I need a way to exit the DLL cleanly from deep inside the calling structure. What is the best way to do that and still allow the calling application to stay alive?

Thanks,
Larry Scheier
0 Kudos
6 Replies
Steven_L_Intel1
Employee
1,021 Views
Fortran has no structured exception handling. If you wrap the Fortran DLL calls in a C++ routine you can use C++ exception handling to return a failure status, but your ability to raise an exception is limited. RAISEQQ can be used for this purpose. I suggest you read through the Error Handling > Handling Run-Time Errors sections of the documentation.
0 Kudos
larryscheier
Beginner
1,021 Views
Sorry, my question was not clear. The code is able to catch user input errors that might otherwise cause the DLL to crash due to an exception. The problem is how do I terminate the DLL from deep inside a nest of calling routines without causing the calling application to crash.

SUBROUTINE MyDLL()
!DEC$ATTRIBUTES DLLEXPORT :: MyDLL
CALL Sub1()
RETURN
END SUBROUTINE

SUBROUTINE Sub1()
CALL Sub2()
RETURN
END SUBROUTINE

SUBROUTINE Sub2()
CALL Sub3()
RETURN
END SUBROUTINE
....
SUBROUTINE Sub100()
CALL Sub101()
RETURN
END SUBROUTINE

SUBROUTINE Sub101()
...do stuff until someting suspicious in user input
CALL OutputErrMessage()
RETURN
END SUBROUTINE

SUBROUTINE OutputErrMessage()
Ret = MessageBox( hWnd, "User Error Detected. Exiting MyDll"C, ""C, MB_OK )
EXIT DLL !Exit DLL from here
RETURN
END SUBROUTINE

Obviously, in my simple example, I could just pass a flag back to the mainline MyDLL subroutine and exit from there but my legacy code has over a million lines of code and thousands of calls so that is not practical. Is there a simple solution?
0 Kudos
Steven_L_Intel1
Employee
1,021 Views
Your question was clear. There is no supported way of "cleanly exiting" from a Fortran routine call due to an exception except by returning from the called routine normally. If you absolutely have to do this, you'll need to wrap your calls in C++ code that establishes a try-except block and raising an exception. I will comment that even this may not work for you if your Fortran code depends on preserving contents of variables across calls.

The ideal way to approach this in Fortran is to have functions that return a status value, and then check that status after each call. Anything else is outside the language's capability.
0 Kudos
bmchenry
New Contributor II
1,021 Views
I would suggest you break the former DOS programinto several dlls;
one with all routines for input,
one with all routines for output,
one or more with all thecalculations and/or whatever other specialized routines the former DOS program did.
one for the variables/data storage (move all data and common blocksinto modules and then contain them in a separate dll whcih you share between all the dlls as needed).
And then rather then need toterminate the dll, you simply return with the error codes, flags or whatever you need to identify what went wrong andthen simply re-initialize the data and start/restart/resume the calling sequence.
You will be rewarded in saved time in the long runby taking take some time breaking it up now rather than later.
0 Kudos
jimdempseyatthecove
Honored Contributor III
1,021 Views
As Steve mentioned, there is no structured exception handling in Fortran. A C++ wrapper is nota suitable solution in a general sense because if you were to use something like setjmp/longjmp (or ex versions) there is no code that will clean-up the auto allocate/deallocate arrays that may exist in your call tree. The best way is to return a status, then test status and dispatch accordingly. Your C++ library functions called from Fortran should be called via a C++ shell with try/catch that then converts the catch error code into your error(or success) return status.

Jim Dempsey
0 Kudos
jimdempseyatthecove
Honored Contributor III
1,021 Views
One potential (untested) technique is to call your DLL via a C++ shell function and in the shell function replace the CRTL malloc/free/new/delete handler with your own handler that uses an entirely seperate stack. You then may be able to throw an exception, effectively unstacking the calls, then "evaporating" your alternate heap and Fortran auto allocated arrays, andexplicitly allocated to local arrays/pointers/***and return allocatablereferences***(delete private heap after extracting potentially allocated return objects). Then return to caller with results and error/success indication.

Jim Dempsey
0 Kudos
Reply