From: khan AT xraylith DOT wisc DOT edu (Mumit Khan) Subject: DLL init patch for loading cygwin DLL from MSVC app 28 Oct 1998 17:26:32 -0800 Message-ID: <9810290044.AA29361.cygnus.cygwin32.developers@modi.xraylith.wisc.edu> To: cygwin32-developers AT cygnus DOT com Here's a tentative, and most certainly not completely correct, patch for initializing Cygwin guts when a Cygnus DLL is loaded for the first time from a *non-cygwin* application. I can now load cygwin DLLs from MSVC/Mingw apps as well as build working Java JNI. But of course that doesn't mean that this patch is correct. I would very much appreciate it if folks could take a look and see if this missing anything (or if it's just completely wrong!). Wed Oct 28 18:39:15 1998 Mumit Khan * dll_init.cc (exceptions.h): Include. (dll_dllcrt0_1): New function. (dll_dllcrt0): Use. --- dll_init.cc.~1 Wed Oct 28 15:28:39 1998 +++ dll_init.cc Wed Oct 28 18:38:38 1998 @@ -8,6 +8,7 @@ details. */ #include #include "winsup.h" +#include "exceptions.h" #include "dll_init.h" extern void check_sanity_and_sync (per_process *); @@ -395,9 +396,89 @@ LoadedDllNameIterator::~LoadedDllNameIte // the extern symbols extern "C" +{ + /* This is an exported copy of environ which can be used by DLLs + which use cygwin.dll. */ + extern struct _reent reent_data; +}; + +/* Initialize Cygwin DLL. This is only done if this is the first cygwin + DLL to be loaded and the main app is not Cygwin. */ +static void +dll_dllcrt0_1 (per_process *uptr) +{ + /* According to onno AT stack DOT urc DOT tue DOT nl, the exception handler record must + be on the stack. */ + /* FIXME: Verify forked children get their exception handler set up ok. */ + struct exception_list cygwin_except_entry; + + check_sanity_and_sync (uptr); + + /* Set the local copy of the pointer into the user space. */ + user_data = uptr; + + /* Nasty static stuff needed by newlib -- point to a local copy of + the reent stuff. + Note: this MUST be done here (before the forkee code) as the + fork copy code doesn't copy the data in libccrt0.cc (that's why we + pass in the per_process struct into the .dll from libccrt0). */ + + *(user_data->impure_ptr_ptr) = &reent_data; + _impure_ptr = &reent_data; + + /* Initialize the cygwin32 subsystem if this is the first process, + or attach to the shared data structure if it's already running. */ + shared_init (); + + /* Initialize events. */ + events_init (); + + (void) SetErrorMode (SEM_FAILCRITICALERRORS); + + /* Initialize the heap. */ + heap_init (); + + /* Initialize SIGSEGV handling, etc... Because the exception handler + references data in the shared area, this must be done after + shared_init. */ + init_exceptions (&cygwin_except_entry); + + /* Nasty static stuff needed by newlib - initialize it. + Note that impure_ptr has already been set up to point to this above + NB. This *MUST* be done here, just after the forkee code as some + of the calls below (eg. uinfo_init) do stdio calls - this area must + be set to zero before then. */ + + memset (&reent_data, 0, sizeof (reent_data)); + reent_data._errno = 0; + reent_data._stdin = reent_data.__sf + 0; + reent_data._stdout = reent_data.__sf + 1; + reent_data._stderr = reent_data.__sf + 2; + + /* Allocate dtable */ + dtable_init (); + + /* Connect to tty. */ + tty_init (); + + /* Set up standard fds in file descriptor table. */ + hinfo_init (); + + /* Call init of loaded dlls. */ + DllList::the().initAll(); + + set_errno (0); +} + +extern "C" int dll_dllcrt0 (HMODULE h, per_process *p) { + /* initialize Cygwin guts if not already done. */ + if (user_data == NULL) + { + dll_dllcrt0_1 (p); + } return _the.recordDll (h, p); } Regards, Mumit