Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.

Creating redirected console for DLL

jimdempseyatthecove
Honored Contributor III
622 Views

I recently had (still do) a problem in getting diagnostic information out of a Fortran DLL containing offloads to Xeon Phi coprocessor. The host application was a C# forms application with no console. To aid in debugging, there are some diagnostic options you can set in the environment variables (H_TRACE, etc). Using the Kernel32 function AllocConsole() worked for the most part. The "gotcha" that got me now is one of those "Heisenbugs" - the kind that when you look for them, their not there.

What I wanted to do is to run the Release build, with debugging information, in the Amplifier (aka VTune). The release code image would run without the debugger and outside of the Amplifier. Same image would run when launched for a debug session. However, when attempting an Amplifier run the application would crash on the first offload *** before any of the offload code got loaded ***. (I could run the Amplifier using the Debug build). Unfortunately, when the crash occurs the console window closes and any information gets lost. To correct for this, I needed to add a redirected to file console to a non-console application. I thought I should share the code for those in a similar pickle:

!DIR$ IF (.TRUE.)
! enable this section to get console ouput for debugging of MIC offloads
function DllMain (hInstDLL, fdwReason, lpReserved)
!DEC$ ATTRIBUTES STDCALL, DECORATE, DLLEXPORT, ALIAS:"DllMain" :: DllMain
    USE IFWINTY
    USE Kernel32
    
    IMPLICIT NONE
    integer(BOOL) :: DllMain
    integer(HANDLE), intent(IN) :: hinstDLL
    integer(DWORD), intent(IN) :: fdwReason
    integer(LPVOID), intent(IN) :: lpReserved
    
    character(500) :: eVar
    character(500) :: fName
    logical :: exists
    logical, save :: FirstTime = .true.
    
    integer(BOOL) :: b
    integer(HANDLE) :: hConFile
    interface
        INTEGER FUNCTION internal_crames_try_offload_mic(iMIC)
            integer :: iMIC
        end FUNCTION internal_crames_try_offload_mic
    end interface
    
    select case(fdwReason)
    case (DLL_PROCESS_DETACH)
       ! ...
        DllMain = TRUE
    case (DLL_PROCESS_ATTACH)
!DIR$ IF(.FALSE.)
     b = AllocConsole()
!DIR$ ELSE
        hConFile = CreateFile("C:\\DebugOutput\\ConsoleOutput.txt"C, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0)
        b=SetStdHandle(STD_OUTPUT_HANDLE, hConFile)
!DIR$ ENDIF
        write(*,*) "***************************"
        CALL GET_ENVIRONMENT_VARIABLE("MIC_LIBRARY_PATH",eVar)
        write(*,*) "MIC_LIBRARY_PATH=",TRIM(eVar)
        CALL GET_ENVIRONMENT_VARIABLE("MIC_LD_LIBRARY_PATH",eVar)
        write(*,*) "MIC_LD_LIBRARY_PATH=",TRIM(eVar)
        write(*,*) "***************************"
    case (DLL_THREAD_ATTACH)
        ! ...
    case (DLL_THREAD_DETACH)
        ! ...
    case default
        ! ...
    end select
    DllMain = TRUE
    write(*,*) "DllMain(",hInstDLL, ",", fdwReason, ",", lpReserved,")"
    end function DllMain
!DIR$ ENDIF

Now for the "Heisenbug" part. Adding the conditional compile statements to switch from AllocConsole and SetStdHandle caused the application to not crash. In any event, I am all set to catch any fleeting output should the bug crop up again.

Jim Dempsey

0 Kudos
3 Replies
jimdempseyatthecove
Honored Contributor III
622 Views

You can remove and ignore the ...try_offload interface. That was leftover from various diagnostic code I and been using.

Jim Dempsey

0 Kudos
FortranFan
Honored Contributor III
622 Views

Jim,

I'm sure I'm missing your point altogether, for I don't understand why one would want to "add a redirected to file console to a non-console application".  When exactly does such a need come into play?

You say, "the host application was a C# forms application with no console".  C# as part of Microsoft .NET is super, super rich environment from a UI point-of-view.  Given its extreme richness and programming ease-of-use, I find few developers, if any, bother with console and redirected file, etc.,  

See this thread, especially Message #2.

In C# or .NET in general, as you would know, one can easily put together any of a number of UI control options, say panels, to display messages; think of the "Output" window of Visual Studio for a simple example.  Such UI controls may be tabbed/layered/partitioned, etc. to create multiple views, say one for each module/entity/DLL the host application is working with at a given instance.  By including a callback facility on the Fortran DLL side as shown in Message #2 of above thread, one can route all kind of information and messages back, all this while keeping Fortran code fully standards compliant (no need for compiler directives, etc.) and simple.  And if the host application doesn't allow for this, one can have an intermediate UI layer or tier to which the callback sends messages.

Is there a particular reason why such an approach can't be followed in your situation?

0 Kudos
jimdempseyatthecove
Honored Contributor III
622 Views

FortranFan,

Yes, you are missing the point. I am NOT talking about a preference to use a Console Window over the use of the UI interface. What I am talking about is....

a) Application program is written using C# Forms with its elegant UI and missing Console Window (the way I want the program to run)
b) I supply a DLL (also no console window)  (the way I want the program to run)
c) My DLL performs an offload using 3rd party libraries (Part of Intel MPSS and MIC Offload compiler)
d) When everything is working correctly I want it to run without a Console Window
e) When the offload craps out,  the 3rd party libraries (Part of Intel MPSS and MIC Offload compiler), when enabled with environment variable(s) optionally write diagnostic information... *** to the (missing) console window *** Therefore for diagnostic reasons I conditionally add an AllocConsole such that the diagnostic information has somewhere to be written.
f) When this error occurs in my code, there is an orderly application shutdown (unwind) and I can break in my inserted DllMain DLL_PROCESS_DETACH dispatch routine and thus have an opportunity to read the error message (and any trace message) printed to the "console"
---- now here is the bugaboo ---
g) Should the error occur early on in the "inject the offload code into the MIC" procedure, the application terminates without opportunity to trap in the DllMain DLL_PROCESS_DETACH. And the console window immediately closes without opportunity to read what was on the screen. (along with anything the C# Forms UI had on the display).

Ergo - I needed a means of capturing the (temporarily added diagnostic) console window output. Unfortunately, adding the redirected output caused the symptom to disappear. For now, Amplifier/VTune runs the Release mode of the application without crashing.

I hope the cascade of 7 conditions is not too hard to follow.

Jim Dempsey

0 Kudos
Reply