Opened 8 years ago

Closed 8 years ago

Last modified 4 years ago

#732 closed bug (fixed)

Error in shutdownHaskell() in Win32 DLL

Reported by: cschmidt@… Owned by:
Priority: normal Milestone: 6.4.2
Component: Runtime System Version: 6.4.1
Keywords: Cc:
Operating System: Windows Architecture: Unknown/Multiple
Type of failure: Difficulty: Easy (less than 1 hour)
Test Case: Blocked By:
Blocking: Related Tickets:

Description

If an exception occurs in a Windows DLL produced by GHC,
the following error message appears:

ghcDll: internal error: too many hs_exit()s
    Please report this as a bug to glasgow-haskell-bugs@haskell.org,
    or http://www.sourceforge.net/projects/ghc/

How to reproduce

  1. Make a Haskell DLL using the enclosed Dll.hs and dllMain.c, e.g.
    ghc -c Dll.hs -fglasgow-exts
    ghc -c dllMain.c
    ghc --mk-dll -o test.dll Dll.o Dll_stub.o dllMain.o
    
  1. Generate an export library for the DLL, e.g.
    lib /DEF:test.def /MACHINE:x86 /OUT:test.lib
    
  1. Compile the executable with Visual C++ and run it.
    cl -c testdll.cpp
    link testdll.obj test.lib /OUT:testdll.exe
    testdll.exe
    

Note: if I comment out the shutdownHaskell() call from dllMain.c
(the line marked with /*/), it works fine.

Kind regards,

Cyril

--- Dll.hs ---

module Dll (test) where

foreign export ccall test :: IO ()

test = error "Exception occurred"

--- dllMain.c ---

#include <windows.h>
#include <Rts.h>

extern void __stginit_Dll(void);

static char* args[] = { "ghcDll", NULL };

BOOL
STDCALL
DllMain
   ( HANDLE hModule
   , DWORD reason
   , void* reserved
   )
{
  if (reason == DLL_PROCESS_ATTACH) {
      startupHaskell(1, args, __stginit_Dll);
      return TRUE;
  } else if (reason == DLL_PROCESS_DETACH) {
/***/   shutdownHaskell();
  }
  return TRUE;
}

--- test.def ---

EXPORTS
	test

--- testdll.cpp ---

extern "C" void test();

int main() {
	test();
	return 0;
}

Change History (4)

comment:1 Changed 8 years ago by simonmar

I've made the error a warning instead.

Basically the situation is this: it is your responsibility to include exception handlers in foreign exported functions and to return appropriate error values. The only thing that the runtime can do in the event that a foreign exported function raises an exception is to terminate with a fatal error; there's no way to return a value to the caller, because we don't know what value to return.

In your example, the runtime had terminated, and your DLL code attempted to shut it down again. There's no reason this really has to be a fatal error, though.

comment:2 Changed 8 years ago by simonmar

  • Resolution set to fixed
  • Status changed from new to closed

comment:3 Changed 6 years ago by simonmar

  • Architecture changed from Unknown to Unknown/Multiple

comment:4 Changed 4 years ago by simonmar

  • Difficulty changed from Easy (1 hr) to Easy (less than 1 hour)
Note: See TracTickets for help on using tickets.