[Python-checkins] r69476 - in python/branches/py3k: Misc/NEWS Modules/_tkinter.c Modules/tkappinit.c

guilherme.polo python-checkins at python.org
Mon Feb 9 23:33:59 CET 2009


Author: guilherme.polo
Date: Mon Feb  9 23:33:59 2009
New Revision: 69476

Log:
Merged revisions 69473 via svnmerge from 
svn+ssh://pythondev/python/trunk

........
  r69473 | guilherme.polo | 2009-02-09 18:50:27 -0200 (Mon, 09 Feb 2009) | 3 lines
  
  Fixed issue #5122: Synchronize tk load failure check to prevent a
  potential deadlock.
........


Modified:
   python/branches/py3k/   (props changed)
   python/branches/py3k/Misc/NEWS
   python/branches/py3k/Modules/_tkinter.c
   python/branches/py3k/Modules/tkappinit.c

Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS	(original)
+++ python/branches/py3k/Misc/NEWS	Mon Feb  9 23:33:59 2009
@@ -163,6 +163,9 @@
 Library
 -------
 
+- Issue #5122: Synchronize tk load failure check to prevent a potential
+  deadlock.
+
 - Issue #4890: Handle empty text search pattern in Tkinter.Text.search.
 
 - Issue #4512 (part 2): Promote ``ZipImporter._get_filename()`` to be a

Modified: python/branches/py3k/Modules/_tkinter.c
==============================================================================
--- python/branches/py3k/Modules/_tkinter.c	(original)
+++ python/branches/py3k/Modules/_tkinter.c	Mon Feb  9 23:33:59 2009
@@ -33,6 +33,8 @@
 #include <windows.h>
 #endif
 
+#include "tkinter.h"
+
 /* Allow using this code in Python 2.[12] */
 #ifndef PyDoc_STRVAR
 #define PyDoc_STRVAR(name,str) static char name[] = str
@@ -74,9 +76,7 @@
 #define CONST
 #endif
 
-#define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
-
-#if TKMAJORMINOR < 8002
+#if TK_VERSION_HEX < 0x08020002
 #error "Tk older than 8.2 not supported"
 #endif
 
@@ -280,6 +280,9 @@
 static PyObject *valInCmd;
 static PyObject *trbInCmd;
 
+#ifdef TKINTER_PROTECT_LOADTK
+static int tk_load_failed;
+#endif
 
 
 static PyObject *
@@ -553,21 +556,35 @@
 int
 Tcl_AppInit(Tcl_Interp *interp)
 {
-	Tk_Window main;
 	const char * _tkinter_skip_tk_init;
 
 	if (Tcl_Init(interp) == TCL_ERROR) {
 		PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
 		return TCL_ERROR;
 	}
-	_tkinter_skip_tk_init =	Tcl_GetVar(interp, "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
-	if (_tkinter_skip_tk_init == NULL || strcmp(_tkinter_skip_tk_init, "1")	!= 0) {
-		main = Tk_MainWindow(interp);
-		if (Tk_Init(interp) == TCL_ERROR) {
-			PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
-			return TCL_ERROR;
-		}
+
+	_tkinter_skip_tk_init = Tcl_GetVar(interp,
+			"_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
+	if (_tkinter_skip_tk_init != NULL &&
+			strcmp(_tkinter_skip_tk_init, "1") == 0) {
+		return TCL_OK;
+	}
+
+#ifdef TKINTER_PROTECT_LOADTK
+	if (tk_load_failed) {
+		PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
+		return TCL_ERROR;
+	}
+#endif
+
+	if (Tk_Init(interp) == TCL_ERROR) {
+#ifdef TKINTER_PROTECT_LOADTK
+		tk_load_failed = 1;
+#endif
+		PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
+		return TCL_ERROR;
 	}
+
 	return TCL_OK;
 }
 #endif /* !WITH_APPINIT */
@@ -650,8 +667,15 @@
 	ckfree(argv0);
 
 	if (! wantTk) {
-	    Tcl_SetVar(v->interp, "_tkinter_skip_tk_init", "1",	TCL_GLOBAL_ONLY);
+		Tcl_SetVar(v->interp,
+				"_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
 	}
+#ifdef TKINTER_PROTECT_LOADTK
+	else if (tk_load_failed) {
+		Tcl_SetVar(v->interp,
+				"_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
+	}
+#endif
 
 	/* some initial arguments need to be in argv */
 	if (sync || use) {
@@ -686,6 +710,18 @@
 
 	if (Tcl_AppInit(v->interp) != TCL_OK) {
 		PyObject *result = Tkinter_Error((PyObject *)v);
+#ifdef TKINTER_PROTECT_LOADTK
+		if (wantTk) {
+			const char *_tkinter_tk_failed;
+			_tkinter_tk_failed = Tcl_GetVar(v->interp,
+					"_tkinter_tk_failed", TCL_GLOBAL_ONLY);
+
+			if ( _tkinter_tk_failed != NULL &&
+					strcmp(_tkinter_tk_failed, "1") == 0) {
+				tk_load_failed = 1;
+			}
+		}
+#endif
 		Py_DECREF((PyObject *)v);
 		return (TkappObject *)result;
 	}
@@ -2547,22 +2583,21 @@
 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;
 	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");
+#ifdef TKINTER_PROTECT_LOADTK
+	/* Up to Tk 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 (tk_load_failed) {
+		PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
 		return NULL;
 	}
+#endif
 
 	/* We want to guard against calling Tk_Init() multiple times */
 	CHECK_TCL_APPARTMENT;
@@ -2582,8 +2617,10 @@
 	}
 	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;
+			PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
+#ifdef TKINTER_PROTECT_LOADTK
+			tk_load_failed = 1;
+#endif
 			return NULL;
 		}
 	}

Modified: python/branches/py3k/Modules/tkappinit.c
==============================================================================
--- python/branches/py3k/Modules/tkappinit.c	(original)
+++ python/branches/py3k/Modules/tkappinit.c	Mon Feb  9 23:33:59 2009
@@ -16,11 +16,21 @@
 #include <tcl.h>
 #include <tk.h>
 
+#include "tkinter.h"
+
+#ifdef TKINTER_PROTECT_LOADTK
+/* See Tkapp_TkInit in _tkinter.c for the usage of tk_load_faile */
+static int tk_load_failed;
+#endif
+
 int
 Tcl_AppInit(Tcl_Interp *interp)
 {
 	Tk_Window main_window;
-	const char * _tkinter_skip_tk_init;
+	const char *_tkinter_skip_tk_init;
+#ifdef TKINTER_PROTECT_LOADTK
+	const char *_tkinter_tk_failed;
+#endif
 
 #ifdef TK_AQUA
 #ifndef MAX_PATH_LEN
@@ -74,12 +84,32 @@
 		/* Initialize modules that don't require Tk */
 #endif
 
-	_tkinter_skip_tk_init =	Tcl_GetVar(interp, "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
-	if (_tkinter_skip_tk_init != NULL && strcmp(_tkinter_skip_tk_init, "1")	== 0) {
+	_tkinter_skip_tk_init =	Tcl_GetVar(interp,
+			"_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
+	if (_tkinter_skip_tk_init != NULL &&
+			strcmp(_tkinter_skip_tk_init, "1") == 0) {
 		return TCL_OK;
 	}
-	if (Tk_Init(interp) == TCL_ERROR)
+
+#ifdef TKINTER_PROTECT_LOADTK
+	_tkinter_tk_failed = Tcl_GetVar(interp,
+			"_tkinter_tk_failed", TCL_GLOBAL_ONLY);
+
+	if (tk_load_failed || (
+				_tkinter_tk_failed != NULL &&
+				strcmp(_tkinter_tk_failed, "1") == 0)) {
+		Tcl_SetResult(interp, TKINTER_LOADTK_ERRMSG, TCL_STATIC);
 		return TCL_ERROR;
+	}
+#endif
+
+	if (Tk_Init(interp) == TCL_ERROR) {
+#ifdef TKINTER_PROTECT_LOADTK
+		tk_load_failed = 1;
+		Tcl_SetVar(interp, "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
+#endif
+		return TCL_ERROR;
+	}
 
 	main_window = Tk_MainWindow(interp);
 


More information about the Python-checkins mailing list