]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Work around deadlock risk.
authorMartin v. Löwis <martin@v.loewis.de>
Mon, 1 May 2006 06:29:06 +0000 (06:29 +0000)
committerMartin v. Löwis <martin@v.loewis.de>
Mon, 1 May 2006 06:29:06 +0000 (06:29 +0000)
Misc/NEWS
Modules/_tkinter.c

index f647d1f405015214e7b47f3bde09a46f79c81279..593a881df60457d2e2ad4ce9ace2ee1c61e08cee 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -15,6 +15,9 @@ Core and builtins
 Extension Modules
 -----------------
 
+- Calling Tk_Init twice is refused if the first call failed as that
+  may deadlock.
+
 - Patch #1191065: Fix preprocessor problems on systems where recvfrom
   is a macro.
 
index bc64ad1d113c2ff117602475404eaa2a5829d72c..82be5ac1ca9215fa450db339624e28f63339d804 100644 (file)
@@ -2609,20 +2609,32 @@ Tkapp_InterpAddr(PyObject *self, PyObject *args)
 static PyObject        *
 Tkapp_TkInit(PyObject *self, PyObject *args)
 {
+       static int has_failed;
        Tcl_Interp *interp = Tkapp_Interp(self);
        Tk_Window main_window;
        const char * _tk_exists = NULL;
-       PyObject *res = NULL;
        int err;
        main_window = Tk_MainWindow(interp);
 
+       /* In all current versions of Tk (including 8.4.13), Tk_Init
+          deadlocks on the second call when the first call failed.
+          To avoid the deadlock, we just refuse the second call through
+          a static variable. */
+       if (has_failed) {
+               PyErr_SetString(Tkinter_TclError, 
+                               "Calling Tk_Init again after a previous call failed might deadlock");
+               return NULL;
+       }
+          
        /* We want to guard against calling Tk_Init() multiple times */
        CHECK_TCL_APPARTMENT;
        ENTER_TCL
        err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
        ENTER_OVERLAP
        if (err == TCL_ERROR) {
-               res = Tkinter_Error(self);
+               /* This sets an exception, but we cannot return right
+                  away because we need to exit the overlap first. */
+               Tkinter_Error(self);
        } else {
                _tk_exists = Tkapp_Result(self);
        }
@@ -2633,6 +2645,7 @@ Tkapp_TkInit(PyObject *self, PyObject *args)
        if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
                if (Tk_Init(interp)     == TCL_ERROR) {
                        PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
+                       has_failed = 1;
                        return NULL;
                }
        }