[PyQt] patch to fix segfault on mac

Erick Tryzelaar idadesub at users.sourceforge.net
Wed Jun 4 05:09:25 BST 2008


I tracked down another segfault for me on the mac. I wasn't able to do
"import PyQt4.QtWebKit" using the sip 4.7.4 and pyqt4 4.4.2. The
problem turned out to be how the superclasses were looked up during
the code generation of QWebView. As far as I can tell, superclasses
are looked up via an index in supers_QWebView:

/* Define this type's super-types. */
static sipEncodedClassDef supers_QWebView[] = {{251, 1, 1}};

The second number, 1, is the important one here. This then is looked
up in QtWebKit's importsTable:

/* This defines the modules that this module needs to import. */
static sipImportedModuleDef importsTable[] = {
    {"PyQt4.QtCore", 0, NULL},
    {"PyQt4.QtNetwork", 0, NULL},
    {"PyQt4.QtGui", 0, NULL},
    {NULL, -1, NULL}
};

The problem is that the index is wrong. The class that it's trying to
look up is QWidget, which obviously lives in QtGui. So, what's going
on? It turns out that the code that generates supers_QWebView looks up
the index in the global module list. After the sip files are parsed,
the imports are resolved and the ordering of the modules is cached
into each module. In my case, those modules are this, in order:

0: QtCore
1: QtGui
2: QtNetwork
3: QtPhonon
...

The rest aren't important in this case. At runtime, the module index
stored in supers_QWebView is used to find the runtime superclass. It
does this by looking up the data in QtWebKit's importsTable. As you
can see, if we take index=1 from the importsTable, we'll get
QtNetwork, which will eventually result in a segfault.

Long story short, I've attached a hacked together patch to fix this.
All I change is that instead of using the cached module index number,
I recalculate it by walking through all the imports in the module to
find the right index. There probably are cleaner ways of doing this,
but with it I'm able to import and use all the pyqt4 modules.

Finally, one thing we found is that if we built pyqt4 against sip
4.7.6, but ran it with sip 4.7.4, it wouldn't segfault. Switching back
to the 4.7.6 runtime it'd go back to crashing. We haven't investigated
what's changed too deeply, though, so maybe the real bug is in the
runtime.


--- sipgen/gencode.c
+++ sipgen/gencode.c
@@ -2152,10 +2152,19 @@ static void generateEncodedClass(moduleDef
*mod, classDef *cd, int last,

     prcode(fp, "{%u, ", cd->classnr);

-    if (cmod == mod)
+    if (cmod == mod) {
         prcode(fp, "255");
-    else
-        prcode(fp, "%u", cmod->modulenr);
+    } else {
+        moduleListDef* m = mod->allimports;
+        int i = 0;
+
+        for (; m != NULL; m = m->next, i++) {
+            if (cmod == m->module) {
+                prcode(fp, "%u", i);
+                break;
+            }
+        }
+    }

     prcode(fp, ", %u}", last);
 }


More information about the PyQt mailing list