From 8672519ac0617dcc0ec95ead7ee28ec6040f5741 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= <martin@v.loewis.de>
Date: Mon, 1 May 2006 06:28:01 +0000
Subject: Work around deadlock risk. Will backport.

---
 Misc/NEWS          |  3 +++
 Modules/_tkinter.c | 18 +++++++++++++++---
 2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/Misc/NEWS b/Misc/NEWS
index 3bd5a1f..1a180c2 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -63,6 +63,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.
 
diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c
index ebaf799..bbcbfa1 100644
--- a/Modules/_tkinter.c
+++ b/Modules/_tkinter.c
@@ -2619,21 +2619,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) {
-		/* XXX: shouldn't we do something with res? */
-		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);
 	}
@@ -2644,6 +2655,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;
 		}
 	}
-- 
cgit v0.12

