Re: Calling ghc dll's with MSVC++ code

Hmmm, I just now came across this: "I'm not confident that creating Haskell DLLs is working at the moment. Has anyone else done it?" I have. Or rather, I haven't. The example in Section 11.4 of the User's Guide doesn't work. The call to "startupHaskell()" hangs forever (or as long as I'm willing to wait). It works fine when the exact same call to startupHaskell is linked statically. "Trouble is, there isn't yet a critical mass of DLL users to be sure that it works and stays working. Which is a bit of a chicken and egg problem. Windows programmers unite!" Is two a critical mass? -- Kevin S. Millikin Architecture Technology Corporation Research Scientist Specialists in Computer Architecture (952)829-5864 x. 162 http://www.atcorp.com

"Kevin" == Kevin S Millikin
writes:
Kevin> I have. Or rather, I haven't. The example in Section 11.4 Kevin> of the User's Guide doesn't work. The call to Kevin> "startupHaskell()" hangs forever (or as long as I'm willing Kevin> to wait). Kevin> It works fine when the exact same call to startupHaskell is Kevin> linked statically. I've done some rooting around in the GHC sources and tracing in a debugger, and I know more about *where* it goes wrong. To recap: the example of Haskell code in a Windows DLL in Section 11.4 of the User's Guide does not work. The call to startupHaskell(...) does not return. (On Windows NT, using GHC 5.04.2). startupHaskell is in rts/RtsStartup.c. It calls a bunch of stuff, then calls startVirtTimer(...), which never returns. startVirtTimer is in rts/Itimer.c. It calls some stuff, then calls the Windows SDK function timeSetEvent(...). timeSetEvent is in the multimedia DLL WINMM.DLL. Here's where it gets fuzzy. Eventually, WINMM.DLL calls into KERNEL32.DLL. Eventually that calls into NTDLL.DLL. NTDLL issues the x86 instruction: int 2Eh Which is an interrupt. The debugger can't tell me where this tries to go; it never gets back. Anyone have any idea what this interrupt is? Is it a callback to Haskell? Since this is in one of the Windows NT system DLLs, it's tempting to call it an "OS" problem, but it doesn't feel like it. Curiously, the exact same code continues to work perfectly when the code that contains the call to startupHaskell is linked statically (and with an explicit call to DllMain). Perhaps someone with more knowledge of Windows DLLs has some idea. Or possibly, what is the call to startVirtTimer doing? Would it be possible to replace it with some alternative that would work when linked either statically or dynamically? -- Kevin S. Millikin Architecture Technology Corporation Research Scientist Specialists in Computer Architecture (952)829-5864 x. 162 http://www.atcorp.com

"Kevin S. Millikin"
...
timeSetEvent is in the multimedia DLL WINMM.DLL. Here's where it gets fuzzy. Eventually, WINMM.DLL calls into KERNEL32.DLL. Eventually that calls into NTDLL.DLL. NTDLL issues the x86 instruction:
int 2Eh
Which is an interrupt. The debugger can't tell me where this tries to go; it never gets back. Anyone have any idea what this interrupt is?
That's the system trap interrupt (i.e., transition to ring 0 / kernel mode to perform a system call/service.) --sigbjorn

"Sigbjorn" == Sigbjorn Finne
writes:
Sigbjorn> That's the system trap interrupt (i.e., transition to Sigbjorn> ring 0 / kernel mode to perform a system call/service.) Thanks! I've learned more about Windows and DLLs in a few days than I ever expected or wanted to. The problem appears to be related to http://support.microsoft.com/default.aspx?scid=kb%3ben-us%3b153867 and http://support.microsoft.com/default.aspx?scid=kb%3bEN-US%3b142243 int 0x2e is (presumably) an attempt to attach to the (my) DLL. DllMain is (by design) not reentrant. An attempt to create a thread from DllMain would attach to the DLL, calling DllMain with a reason of DLL_THREAD_ATTACH. This latter call will hang until the original call returns (which will never happen, now). timeSetEvent creates a new thread; and the callback is in the same DLL as the call to startupHaskell. The workaround appears to be to not put code that might possibly create a new thread (that needs the DLL) in DllMain; instead such code should go in an initialization function that is called after DllMain returns. I'll test it out and post code that corrects the example from the User's Guide. -- Kevin S. Millikin Architecture Technology Corporation Research Scientist Specialists in Computer Architecture (952)829-5864 x. 162 http://www.atcorp.com
participants (2)
-
Kevin S. Millikin
-
Sigbjorn Finne