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

Inter routine communications

rahzan
New Contributor I
985 Views
I have an app (really a cvf com server) which calls a fortran DLL which in turn USEs a module for general purpose (ODBC) functions, call this GPmod.

I write the code for the com server and the GPMod but the DLL is supplied by someone else. (though I may be able to get the source and add certain general stataments to it and recompile it, as long as it does not interfere with the details of the computation therein).

What I would like to do is gain access from the main app (which is the com server) to the errors generated by the GPMod. iow, I do not want to rely on the intermediate routine (in the DLL) to pass the errors from the GPmod to the com server.

I suppose I need to produce something like TRY-CATCH as in Java!

I have looked at Threads and Timers, but being rather unfamiliar with threads, I do not know if these are even the right things to use.

I'd apprecaite any ideas.

Thanks in adv.
Tim
0 Kudos
6 Replies
Jugoslav_Dujic
Valued Contributor II
985 Views
Tim, sorry, I don't follow you. OK, the structure is:
Application (COM server)
   +---> 3rd Party dll
            +----> GPmod
but first, it's unclear what is GPmod? Is it a dll of its own, or a MODULE which you compile into that 3rd-party dll, or a set of callbacks called from the dll?

Second, what kind of errors you talk about? As you certainly know, Fortran unfortunately doesn't have structured exception handling (SEH) so about the best you can do is to assure that GPmod never raises an exception such as access violation or divide by zero, and returns a home-brew error code when it encounters an unexpected situation (OK, "unexpected" is the wrong word -- you have to guard against any unusual situation by a lot of IFs, which can be quite tedious -- list of error codes in an application of mine has over 1000 entries).

If I get you right, you're seeking for a manner how to return a home-brew error code clearly to the application? Why simply not use a global variable, or SetLastError/GetLastError APIs (which are really just a convenient wrapper around having a global variable)?

Jugoslav
0 Kudos
rahzan
New Contributor I
985 Views
Your assumptions are correct.
1. the 3rd module (a set of ODBC functions) is compiled into the middle piece which is the DLL, though I suppose I could make the ODBC module into another DLL.

2. I want to return "expected" errors from the ODBC module to the top layer (which happens to be a com server).

3. The ODBC mod does have GetErr functionality, so I CAN wait until the middle layer is done and then query the ODBC mod to see if anything bad happened. What I am hoping to do is to IMMEDIATELY notify the top layer If a fatal error occurs so that in case the middle layer does not have the proper error checking to terminate the whole thing without proceeding further.

Any ideas?
Thanks, Tim
0 Kudos
Jugoslav_Dujic
Valued Contributor II
985 Views
I admit that I'm out of brilliant ideas at the moment. If it's fine to kill entire sub-thing without killing the server as well, you could launch 3rd-party dll calls in a separate thread and then just wait for them in the server. I mean something like:
!==COM Server
hThread = CreateThread(...AWrapperFuncForMiddleTier, LOC(ATypeContainingArgList))
i = WaitForSingleObject(hThread, INFINITE)
iExitCode = GetExitCodeThread(hThread)
if (iExitCode /= E_OK) then
   hLib = LoadLibrary("3rdPartyLib.dll")
   !Restart bloody thing
   call AnInitializationRoutineFromDll
end if
...
!==
integer function AWrapperFuncForMiddleTier(ArgList)
type(T_TypeContainingArgList):: ArgList
call MiddleTierFunc(ArgList%arg1, ArgList%arg2, ....)
AWrapperFuncForMiddleTier = E_OK
end function
!==ODBC module
...
if (AVeryNastyThingHappened) then
   FreeLibraryAndExitThread(GetModuleHandle("3rdParty.dll"), &
   E_MAJOR_BST)
end if
I'm not certain about
a) Whether Fortran RTL will be happy about abrupt exit via FreeLibraryAndExitThread and whether the memory will be freed, i.e. whether memory leaks will occur;
b) What will happen with addresses of functions once you do LoadLibrary again, i.e. whether the Dll will be relocated. You could overcome that by doing dynamic binding with GetProcAddress, but that's tedious. See MAPI.f90 on "modules" section on my home page.

Gerry Thomas, for instance, posted some interesting stuff about error handling recently [maybe he's good at it because he can't write error-free code like us immortals ;-))) ] so perhaps he could provide some advice?

Jugoslav
0 Kudos
rahzan
New Contributor I
985 Views
Thanks,
I will fool aournd with the thing you sent.
It is real nice to know all the stuff one can with the winapi calls.

Also, I'm interested in error handling in general. Where are the postings by this hot-dawgin' dude, Gerry Thomas? R-dey on this forum?

Tim
0 Kudos
Jugoslav_Dujic
Valued Contributor II
985 Views
Well, here's one thread worth leafing through.

Few more thoughts on your problem: exe and dll share the stack, but by default have different heaps. CVF docs suggest that you should link both the .exe and .dll against "Multi threaded DLL" version of run-time library, so that the heap is managed by DFORRT.dll. However, I can imagine the following scenario:

- You ALLOCATE a piece of memory in the dll
- A fatal error occurs and you FreeLibraryAndExitThread so the dll is unloaded.
- The mentioned piece of memory is not released, since the corresponding heap is managed by DFORRT.dll, which is alive & well.

Try experimenting with linking the .exe and the .dll against static version of run-time library. This should work as well if you don't share unit numbers and don't allocate memory in one module and deallocate in another. FreeLibraryAndExitThread should kill Dll's heap in this case as well.

I don't have time to test this approach -- try allocating a huge chunk and experimenting

Note that I'm kinda stabbing in the dark as well -- wish I knew more details about how C and Fortran RTLs work and interact, how threads are managed, how dlls are loaded & unloaded, what happens with dll entry points etc. Steve is there anything on the web worth reading on the subject?

Jugoslav
0 Kudos
Steven_L_Intel1
Employee
985 Views
Start mentioning COM and my eyes glaze over...

I can tell you:

- DFORMT.DLL is the CVF multithreaded support DLL. It will use LIBCMT.DLL when it uses malloc, but sometimes it makes direct calls to the Win32 API for allocations, depending on the size, to work around bugs/limits in malloc on some platforms.

- When a Fortran DLL is unloaded (IF it's unloaded - it's not clear to me that it is in such cases), there is no "rundown" code - anything that was allocated is now inaccessible. So if you're going to be unloading DLLs (something I don't recommend in general), be sure that you've closed down yourself as much as you can.

I don't know of any general reading on this topic.

Steve
0 Kudos
Reply