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.:
RECURSIVE SUBROUTINE foo()
INTEGER:: i = 0 !i is now SAVEd regardless of RECURSIVE
i = 0 !This is fine, i is AUTOMATIC.
There's also AUTOMATIC keyword in CVF, but it's non-standard.
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.
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 :-))
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.