X-Spam-Check-By: sourceware.org Message-ID: <20060309155635.72549.qmail@web53014.mail.yahoo.com> Date: Thu, 9 Mar 2006 07:56:35 -0800 (PST) From: Gary Zablackis Subject: Bug in dlopen() (or following) code in Cygwin1.dll v 1.5.19-4 To: cygwin AT cygwin DOT com MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit X-IsSubscribed: yes Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com Hi, With the release of Cygwin-1.5.19-4, we have had silent crashes of the Computer Algebra System SAGE at startup. I have traced these to an invalid memory access in pthread_key_create() which SHOULD be caught and processed by the fault handler in verifyable_object_isvalid(). However, the program always dies in the return from this routine. After some research, I believe that the crash occurs when loading a dll via dlopen() and the cygwin dll intialization code calls dll:init() which calls run_ctors() which calls (eventually) pthread::once() which calls init_routine() and init_routine() happens to be fc_key_init(). fc_key_init() sets up the pthread_key_t object, calls _sigfe_pthread_key_create() which jumps into pthread_key_create() which calls verifyably_object_isvalid() and we crash. ------------------------------------------------ I think that this is happening if one dlopen()s a dll that is created with -lstdc++. If ANY dll which is created with -lstdc++ is LINKED into the executable, everything gets initialized properly and pthread_key_create() catches the SIGSEGV and continues normally. Here is a simplified test to show what is going on: ------Simple script to put everything together: #!/bin/sh #NOTE: add -DHARDLINKTEST to ct.c compile to get # a non-crashing exe #1st dll to be dlopen()ed only: gcc -DDEBUG -gstabs+ -g3 -fno-strict-aliasing -Wall -c CrashTest.cc -o CrashTest.o g++ -shared ./CrashTest.o -o CrashTest.dll -lstdc++ #2nd dll to linked directly by exe gcc -DDEBUG -gstabs+ -g3 -fno-strict-aliasing -Wall -c Crash2.cc -o Crash2.o g++ -shared -Wl,--out-implib=libCrash2.dll.a -Wl,--export-all-symbols -Wl,--enable-auto-import -Wl,--whole-archive Crash2.o -Wl,--no-whole-archive -o Crash2.dll -lstdc++ #3rd dll without -lstdc++ gcc -DDEBUG -gstabs+ -g3 -fno-strict-aliasing -Wall -c OK.cc -o OK.o g++ -shared ./OK.o -o OK.dll -lstdc++ #exe test program gcc -DDEBUG -gstabs+ -g3 ct.c -o ct.exe -L./ -lCrash2 ------Code for exe (ct.c): #include #include #include extern void test(); /* test function in dlls */ void TestLinked(char* pszdll); void TestLoad(char* pszdll); int main(int argc, char** argv) { int ret; /* NOTE: -DHARDLINKTEST in makefile if you want this to run */ #ifdef HARDLINKTEST TestLinked("./Crash2.dll"); #endif TestLoad("./OK.dll"); TestLoad("./CrashTest.dll"); printf("THAT'S ALL FOLKS\n"); } #ifdef HARDLINKTEST void TestLinked(char* pszdll) { printf("Testing build time linked %s\n", pszdll); _Z4testv(); /* call test() in dll - real code would have __declspec(dllexport), etc and extern "C" syntactic sugar */ } #endif typedef UINT (CALLBACK* LPFNDLLFUNC1)(DWORD,UINT); void TestLoad(char* pszdll) { printf("dlopening %s\n", pszdll); HANDLE hDLL = (HANDLE)dlopen(pszdll); if(hDLL){ printf("Getting proc address for test\n"); LPFNDLLFUNC1 lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL, "_Z4testv"); if (!lpfnDllFunc1){ // handle the error printf("Failed to get the function: %d\n", GetLastError()); FreeLibrary(hDLL); return; } else { // call the function printf("Calling test\n"); UINT uReturnVal = lpfnDllFunc1(0,0); printf("Back from test\n"); } } else printf("Error %d dlopening %s\n", GetLastError(), pszdll); } ------Code for 1st dll (CrashTest.cc): #include using namespace std; void test() { cout << "\tCRASHTEST: This is a test." << endl << "Did you crash?" << endl; } ------Code for 2nd dll (Crash2.cc): #include #include "Crash2.h" using namespace std; void test() { cout << "\tCRASH2: This is a test." << endl << "Did you crash?" << endl; } ------Code for 3rd dll (OK.c): #include #include void test() { printf("\tOK: This is a test.\n"); } ---------------------------------------------- NOTE: I have also tested all of this with __declspec(dllexport) and __declspec(dllimport) and everything works exactly the same Thanks, Gary __________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Problem reports: http://cygwin.com/problems.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/