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

Multithreaded I/O cores when called from DLL

Brian_Francis
Beginner
1,187 Views
Hi,

We've had trouble in the past with I/O and string concatenation operations coring when our application is run as a DLL in a mixed language multithreaded environment. Compaq recommended we call for_rtl_init in the main, which we did and all was well.

Now we're being run in a similar environment where we no longer have any control over the main. Calling for_rtl_init from our DLL does not solve the problem.

For example, the first read cores at:

POS150GM! for__access_threadstor_threads + 78 bytes
POS150GM! for__once_private + 70 bytes
POS150GM! for__access_threadstor_threads + 18 bytes
POS150GM! for__io_return + 236 bytes
POS150GM! for_read_seq_fmt + 1045 bytes
...my Fortran code...


The first write cores at:

POS150GM! for__access_threadstor_threads + 78 bytes
POS150GM! for__once_private + 70 bytes
POS150GM! for__access_threadstor_threads + 18 bytes
POS150GM! for__acquire_threadstor_threads + 13 bytes
POS150GM! for__acquire_lun + 102 bytes
POS150GM! for_write_int_fmt + 26 bytes
...my Fortran code...


Ideas anyone?

Thanks,

Brian.
0 Kudos
10 Replies
Lorri_M_Intel
Employee
1,187 Views
Are you reading or writing to a console? If so, by default, DLLs don't have a console, and you need to create one. (see AllocConsole())

If there is a different problem, could you post a little code?

- Lorri

0 Kudos
Brian_Francis
Beginner
1,187 Views
Actually, the problem can occur just by performing a simple string concatenation (e.g., 'foo'//'bar'). It seems that concatenation and I/O share common low level routines, and these must be initialized by calling the run-time initialization routine from the main.

What I am hoping to find is some way that the for_rtl_init can be called from a DLL (and work), or some alternate technique that will initialize the run-time library code.

We're running 6.6B, so a compiler upgrade is not an option.
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,187 Views
What do you refer to as "main"? Main program's entry point (Program/void main())?

No guaranteees at all, but you might try to supply your own DllMain (aka DllEntryPoint) and call for_rtl_init from there. Here's mine:
integer function DllEntryPoint(hModule, fdwReason, lpvReserved)
!DEC$ATTRIBUTES STDCALL, ALIAS:"_DllEntryPoint@12"::  DllEntryPoint

use dfwin, only: InitializeCriticalSection

implicit none

integer, intent(in)::   hModule, fdwReason, lpvReserved

select case (fdwReason)
case(DLL_PROCESS_ATTACH)
      hDMSDll = hModule
      call SetWrite()
      call InitializeCriticalSection(LOC(CS))
      DllEntryPoint=1
case default
      DllEntryPoint=1
end select

end function DllEntryPoint
If I recall correctly, you must specify DllEntryPoint@8 at Project Settings/Link/Entry point symbol. For possible fdwReasons, see documentation.

Jugoslav

0 Kudos
Brian_Francis
Beginner
1,187 Views
We've already tried this, but from the C++ side, without any success. The code we used was as follows:
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
	switch (fdwReason)
	{
	case DLL_PROCESS_ATTACH:
		for_rtl_init_(0,0);
		break;
	case DLL_PROCESS_DETACH:
		for_rtl_finish_();
		break;
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	default:
		break;
	}
	return TRUE;
}
The online help for the for_rtl_init function states that it must be called from the C/C++ main entry (and this appears accurate based on our results).

We are now going to try plan B, which is to run our Fortran code through F2C and compile using VC++. Messy and time consuming and no guarantees, but we're desperate. I'll post our results, and keep a watch on this thread for other suggestions.

Brian.
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,187 Views
However... Let me see...

I have a setup where a dll (linked against multi-threaded version of the dll) is called from a Delphi caller. I linked it against multi-threaded version of the dll and it indeed crashed on the first string operation. Then I placed a call to for_rtl_init_ in aforementioned DllMain (written in Fortran) on DLL_PROCESS_ATTACH and it worked like charm (didn't try reentrant call though).

Perhaps a stupid question, but have you verified that your DllMain was actually called? I believe you have to set up "Entry point symbol" in linker settings. Maybe the language has something to do with it -- there's a lot of RTL happening behind the scenes (and I admit I don't know exactly what it is).

Jugoslav
0 Kudos
Brian_Francis
Beginner
1,187 Views
Not a stupid question at all! We double checked that the DLL entry point was correctly set (it was). We then added a MessageBox call following the for_rtl_init one. Our message box appeared, followed shortly thereafter by a core.

Thanks for the suggestion.

I've placed a FortranBug.zip file on our FTP site containing a DevStudio workspace that demonstrates the problem with just a few files. We're using DevStudio 6, VC++6.0 SP5, and Compaq VF6.6.B.

  bugexe.dsw           The main DevStudio workspace
  bugexe/bugexe.dsp    Main program project file
         main.cpp      C++ main program
         dummy.for     Fortran file for testing
  mydll/mydll.dsp      The DLL project file
        mydll.for      DLL Fortran code that will core
        mydllc.cpp     DLL main entry
Load the bugexe.dsw workspace, build all and run it and you will get a core dump in mydll.for.

We have found that the problem can be corrected by performing Fortran I/O in the main program. Uncomment the DUMMY call in main.cpp, add the dummy.for file to the bugexe.dsp project and rebuild. Problem is gone!

But unfortunately, in our real-world application we didn't write the main program and so we have no opportunity to call a dummy routine to perform Fortran I/O.

Ideas?

Brian.
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,187 Views
True. What I didn't try last time was to create a thread internally.

I did few experiments and your workspace (appears to) works flawlessly when mydll is linked against multithreaded DLL versions of Fortran and C++ RTL's (DFORMD.dll) (FWIW, I replaced CreateThread with _beginthreadex as well, just in case). Is that an option?

I suggest you send a bug report to Compaq. Your workspace is a cut-down example that vendors, quote, "tend to love". I'm not so versatile in such things to tell you whether the core dump is supposed to be normal under such circumstances. A usual recommendation is to link dlls against DLL RTLs, but I don't know what are grounds for that (situation like yours?).

Jugoslav
0 Kudos
Brian_Francis
Beginner
1,187 Views
You are right -- we could link against DLL versions of the Fortran and C++ RTL's, but we have had bad experiences doing this in the past. I didn't mention that our software is run just about everywhere in the world (except Elbonia, thankfully) and we've had to use static linking to avoid a host of run-time issues. We began statically linking in the mid '90s and since then OS related issues have been minimized.

We will investigate the possibility that the "other vendor" main program, to which we are linked, uses DLL RTL's at the same level or higher than we do. If so, we have a solution!

I won't have an answer on this for about 2 weeks. I'll post again once I know.

Thanks,

Brian.
0 Kudos
hweisberg
Beginner
1,187 Views
What is a "core?"
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,187 Views
http://info.astrian.net/jargon/terms/c/core_dump.html.

Jugoslav

P.S. Add the site to your Favorites -- it's great :-).
0 Kudos
Reply