python aborts

Daniel Colascione dancol@dancol.org
Thu Jul 25 10:18:00 GMT 2013


On 7/25/2013 12:11 AM, Daniel Colascione wrote:
> On 7/24/2013 11:55 PM, Daniel Colascione wrote:
>> Does that help at all?  I only started seeing this problem after I recompiled
>> _wp.dll using gcc 4.7.3.
> 
> Actually, this problem looks a lot like
> http://www.mail-archive.com/gcc@gcc.gnu.org/msg68316.html: neither Python nor
> _wp links dynamically to libgcc, but cygsqlite3-0.dll does.
> 

And this is a very nasty bug; Eli's analysis is correct. Say we have modules Foo
and Bar. Foo links against shared libgcc, but Bar does not. Now, if we load Foo,
load Bar, unload Foo, then unload Bar, then Foo's initialization code finds
libgcc and registers itself with it, but Foo's deinitializaton code doesn't find
libgcc, tries to instead unregister with Foo's internal data structures, finds
them uninitialized, and aborts. No wonder changing Python module order around
makes the problem go away for a little while.

The right fix for libgcc looks something like this:

--- config/i386/cygming-crtbegin.c.orig 2013-07-25 00:07:35.000000000 -0800
+++ config/i386/cygming-crtbegin.c      2013-07-25 00:33:11.000000000 -0800
@@ -82,6 +82,8 @@
 extern void __gcc_register_frame (void);
 extern void __gcc_deregister_frame (void);

+static HANDLE libgcc_dll;
+
 void
 __gcc_register_frame (void)
 {
@@ -94,8 +96,11 @@
   void (*register_frame_fn) (const void *, struct object *);
   HANDLE h = GetModuleHandle (LIBGCC_SONAME);
   if (h)
-    register_frame_fn = (void (*) (const void *, struct object *))
-                       GetProcAddress (h, "__register_frame_info");
+    {
+      libgcc_dll = LoadLibrary (LIBGCC_SONAME); /* Hold reference */
+      register_frame_fn = (void (*) (const void *, struct object *))
+       GetProcAddress (h, "__register_frame_info");
+    }
   else
     register_frame_fn = __register_frame_info;
   if (register_frame_fn)
@@ -124,13 +129,16 @@
 {
 #if DWARF2_UNWIND_INFO
   void *  (*deregister_frame_fn) (const void *);
-  HANDLE h = GetModuleHandle (LIBGCC_SONAME);
-  if (h)
+  if (libgcc_dll)
     deregister_frame_fn = (void* (*) (const void *))
-                         GetProcAddress (libgcc_dl, "__deregister_frame_info");
+      GetProcAddress (libgcc_dll, "__deregister_frame_info");
   else
     deregister_frame_fn = __deregister_frame_info;
   if (deregister_frame_fn)
      deregister_frame_fn (__EH_FRAME_BEGIN__);
+
+  if (libgcc_dll)
+    FreeLibrary (libgcc_dll);
+
 #endif

The problem is that this code is baked into every module compiled with the buggy
libgcc. You have to recompile the world to fix it for good --- except if shared
libgcc is pinned in memory.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 260 bytes
Desc: OpenPGP digital signature
URL: <http://cygwin.com/pipermail/cygwin/attachments/20130725/e101bad3/attachment.sig>


More information about the Cygwin mailing list