- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi All,
Have a quite large program in Fortran that I've converted to a DLL. It takes a bit of time to run (~ 20 secs) and need to be run via a web page.
OK, I have written a Delphi ISAPI DLL that calls this CVF DLL passing it a few startup parameters.
The Delphi DLL can be called by multiple users via the webserver (IIS 5.0).
Now, I assumed that the ISAPI DLL runs each time in its own thread on IIS. I kind of assumed that the called CVF DLL would also have an area to itself.
However, if you call the application twice at the same time, data within the CVF DLL is corrupted/overwritten by the second call if it occurs at the same time.
I.e. call 1 and call 2 both send their startup parameters correctly and on both occasions the CVF DLL recieves them fine (proved that).
However, large data arrays within the CVF DLL are overwritten by data from the 2nd call while the 1st call is progressing.
I've tried using the Multi-Thread Library, but that doesn't seem to help at all.
I need some pointers as for what to look at. Or clues how to force a calling program to use a 'new' copy of the CVF DLL.
Cheers
Ian
Have a quite large program in Fortran that I've converted to a DLL. It takes a bit of time to run (~ 20 secs) and need to be run via a web page.
OK, I have written a Delphi ISAPI DLL that calls this CVF DLL passing it a few startup parameters.
The Delphi DLL can be called by multiple users via the webserver (IIS 5.0).
Now, I assumed that the ISAPI DLL runs each time in its own thread on IIS. I kind of assumed that the called CVF DLL would also have an area to itself.
However, if you call the application twice at the same time, data within the CVF DLL is corrupted/overwritten by the second call if it occurs at the same time.
I.e. call 1 and call 2 both send their startup parameters correctly and on both occasions the CVF DLL recieves them fine (proved that).
However, large data arrays within the CVF DLL are overwritten by data from the 2nd call while the 1st call is progressing.
I've tried using the Multi-Thread Library, but that doesn't seem to help at all.
I need some pointers as for what to look at. Or clues how to force a calling program to use a 'new' copy of the CVF DLL.
Cheers
Ian
Link Copied
4 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The problem is that by default all variables are SAVEd (static) in CVF; that implies that subroutines are not reentrant. To allow reentrancy, all variables have to be either automatic (stack) or allocatable.
Thus, *ALL* routines have to have RECURSIVE attribute. You can achieve the same effect (without adding it to code) by compiling with "Enable recursive routines" or "Variables default to AUTOMATIC" switch (/automatic)(they mean the same IIRC).
But that's not all -- reentrancy means no COMMONs and no changeable global data at all (the latter can be workarounded but I wouldn't go into detail). Further, take care of a gotcha in Fortran standard -- a variable automatically gets SAVEd when initialized via DATA or initialization statement, i.e.:
There's also AUTOMATIC keyword in CVF, but it's non-standard.
HTH
Jugoslav
Thus, *ALL* routines have to have RECURSIVE attribute. You can achieve the same effect (without adding it to code) by compiling with "Enable recursive routines" or "Variables default to AUTOMATIC" switch (/automatic)(they mean the same IIRC).
But that's not all -- reentrancy means no COMMONs and no changeable global data at all (the latter can be workarounded but I wouldn't go into detail). Further, take care of a gotcha in Fortran standard -- a variable automatically gets SAVEd when initialized via DATA or initialization statement, i.e.:
RECURSIVE SUBROUTINE foo() INTEGER:: i = 0 !i is now SAVEd regardless of RECURSIVE INTEGER:: i i = 0 !This is fine, i is AUTOMATIC.
There's also AUTOMATIC keyword in CVF, but it's non-standard.
HTH
Jugoslav
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I suspect that the problem is caused by the DLL being loaded once and multiple threads calling the routines. If there were separate processes calling the DLL, then the reentrancy issue wouldn't matter.
Jugoslav has the correct solution - declare all the routines RECURSIVE or use the compiler option. Note that simply declaring individual variables as AUTOMATIC may not be sufficient because the compiler may still use static storage for temporary values.
Steve
Jugoslav has the correct solution - declare all the routines RECURSIVE or use the compiler option. Note that simply declaring individual variables as AUTOMATIC may not be sufficient because the compiler may still use static storage for temporary values.
Steve
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you both,
I think I'll just sit down and have a play with this outside of the web environment first, much easy to debug.
I've checked also with the Delphi groups and with the IIS groups and they concur that each ISAPI DLL gets its own thread for execution but any external DLLs etc. are run in a single, shared thread. Which I kind of knew anyway :(
By the way, I tend to do more of the Delphi/web stuff nowadays and leave the main Fortran development to the scientists in the team. You should have seen their faces when I told them no more COMMON blocks (which I've been saying for years) and that they will probably have to change all their code :-))
Thanks again.
Ian
I think I'll just sit down and have a play with this outside of the web environment first, much easy to debug.
I've checked also with the Delphi groups and with the IIS groups and they concur that each ISAPI DLL gets its own thread for execution but any external DLLs etc. are run in a single, shared thread. Which I kind of knew anyway :(
By the way, I tend to do more of the Delphi/web stuff nowadays and leave the main Fortran development to the scientists in the team. You should have seen their faces when I told them no more COMMON blocks (which I've been saying for years) and that they will probably have to change all their code :-))
Thanks again.
Ian
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This is indeed going to be a big shock to your Fortran programmers - no global state (no COMMON, no module variables). Rather than using COMMON, they'll have to use local variables (could be ALLOCATABLE) that get passed as arguments. Also, the DLL should be built with the "multithreaded" option selected (and linked against the thread-safe run-time DLLs - these are options under Libraries.)
The Programmer's Guide has some guidance on writing multithreaded applications, though they can skip the part about creating and synchronizing threads.
Steve
The Programmer's Guide has some guidance on writing multithreaded applications, though they can skip the part about creating and synchronizing threads.
Steve

Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page