Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b681df4

Browse files
committed
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. ........
1 parent c1761b7 commit b681df4

3 files changed

Lines changed: 99 additions & 29 deletions

File tree

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,9 @@ Core and Builtins
163163
Library
164164
-------
165165

166+
- Issue #5122: Synchronize tk load failure check to prevent a potential
167+
deadlock.
168+
166169
- Issue #4890: Handle empty text search pattern in Tkinter.Text.search.
167170

168171
- Issue #4512 (part 2): Promote ``ZipImporter._get_filename()`` to be a

Modules/_tkinter.c

Lines changed: 62 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ Copyright (C) 1994 Steen Lumholt.
3333
#include <windows.h>
3434
#endif
3535

36+
#include "tkinter.h"
37+
3638
/* Allow using this code in Python 2.[12] */
3739
#ifndef PyDoc_STRVAR
3840
#define PyDoc_STRVAR(name,str) static char name[] = str
@@ -74,9 +76,7 @@ Copyright (C) 1994 Steen Lumholt.
7476
#define CONST
7577
#endif
7678

77-
#define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
78-
79-
#if TKMAJORMINOR < 8002
79+
#if TK_VERSION_HEX < 0x08020002
8080
#error "Tk older than 8.2 not supported"
8181
#endif
8282

@@ -280,6 +280,9 @@ static PyObject *excInCmd;
280280
static PyObject *valInCmd;
281281
static PyObject *trbInCmd;
282282

283+
#ifdef TKINTER_PROTECT_LOADTK
284+
static int tk_load_failed;
285+
#endif
283286

284287

285288
static PyObject *
@@ -553,21 +556,35 @@ SplitObj(PyObject *arg)
553556
int
554557
Tcl_AppInit(Tcl_Interp *interp)
555558
{
556-
Tk_Window main;
557559
const char * _tkinter_skip_tk_init;
558560

559561
if (Tcl_Init(interp) == TCL_ERROR) {
560562
PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
561563
return TCL_ERROR;
562564
}
563-
_tkinter_skip_tk_init = Tcl_GetVar(interp, "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
564-
if (_tkinter_skip_tk_init == NULL || strcmp(_tkinter_skip_tk_init, "1") != 0) {
565-
main = Tk_MainWindow(interp);
566-
if (Tk_Init(interp) == TCL_ERROR) {
567-
PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
568-
return TCL_ERROR;
569-
}
565+
566+
_tkinter_skip_tk_init = Tcl_GetVar(interp,
567+
"_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
568+
if (_tkinter_skip_tk_init != NULL &&
569+
strcmp(_tkinter_skip_tk_init, "1") == 0) {
570+
return TCL_OK;
571+
}
572+
573+
#ifdef TKINTER_PROTECT_LOADTK
574+
if (tk_load_failed) {
575+
PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
576+
return TCL_ERROR;
570577
}
578+
#endif
579+
580+
if (Tk_Init(interp) == TCL_ERROR) {
581+
#ifdef TKINTER_PROTECT_LOADTK
582+
tk_load_failed = 1;
583+
#endif
584+
PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
585+
return TCL_ERROR;
586+
}
587+
571588
return TCL_OK;
572589
}
573590
#endif /* !WITH_APPINIT */
@@ -650,8 +667,15 @@ Tkapp_New(char *screenName, char *className,
650667
ckfree(argv0);
651668

652669
if (! wantTk) {
653-
Tcl_SetVar(v->interp, "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
670+
Tcl_SetVar(v->interp,
671+
"_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
672+
}
673+
#ifdef TKINTER_PROTECT_LOADTK
674+
else if (tk_load_failed) {
675+
Tcl_SetVar(v->interp,
676+
"_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
654677
}
678+
#endif
655679

656680
/* some initial arguments need to be in argv */
657681
if (sync || use) {
@@ -686,6 +710,18 @@ Tkapp_New(char *screenName, char *className,
686710

687711
if (Tcl_AppInit(v->interp) != TCL_OK) {
688712
PyObject *result = Tkinter_Error((PyObject *)v);
713+
#ifdef TKINTER_PROTECT_LOADTK
714+
if (wantTk) {
715+
const char *_tkinter_tk_failed;
716+
_tkinter_tk_failed = Tcl_GetVar(v->interp,
717+
"_tkinter_tk_failed", TCL_GLOBAL_ONLY);
718+
719+
if ( _tkinter_tk_failed != NULL &&
720+
strcmp(_tkinter_tk_failed, "1") == 0) {
721+
tk_load_failed = 1;
722+
}
723+
}
724+
#endif
689725
Py_DECREF((PyObject *)v);
690726
return (TkappObject *)result;
691727
}
@@ -2547,22 +2583,21 @@ Tkapp_InterpAddr(PyObject *self, PyObject *args)
25472583
static PyObject *
25482584
Tkapp_TkInit(PyObject *self, PyObject *args)
25492585
{
2550-
static int has_failed;
25512586
Tcl_Interp *interp = Tkapp_Interp(self);
2552-
Tk_Window main_window;
25532587
const char * _tk_exists = NULL;
25542588
int err;
2555-
main_window = Tk_MainWindow(interp);
2556-
2557-
/* In all current versions of Tk (including 8.4.13), Tk_Init
2558-
deadlocks on the second call when the first call failed.
2559-
To avoid the deadlock, we just refuse the second call through
2560-
a static variable. */
2561-
if (has_failed) {
2562-
PyErr_SetString(Tkinter_TclError,
2563-
"Calling Tk_Init again after a previous call failed might deadlock");
2589+
2590+
#ifdef TKINTER_PROTECT_LOADTK
2591+
/* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2592+
* first call failed.
2593+
* To avoid the deadlock, we just refuse the second call through
2594+
* a static variable.
2595+
*/
2596+
if (tk_load_failed) {
2597+
PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
25642598
return NULL;
25652599
}
2600+
#endif
25662601

25672602
/* We want to guard against calling Tk_Init() multiple times */
25682603
CHECK_TCL_APPARTMENT;
@@ -2582,8 +2617,10 @@ Tkapp_TkInit(PyObject *self, PyObject *args)
25822617
}
25832618
if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
25842619
if (Tk_Init(interp) == TCL_ERROR) {
2585-
PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
2586-
has_failed = 1;
2620+
PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
2621+
#ifdef TKINTER_PROTECT_LOADTK
2622+
tk_load_failed = 1;
2623+
#endif
25872624
return NULL;
25882625
}
25892626
}

Modules/tkappinit.c

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,21 @@
1616
#include <tcl.h>
1717
#include <tk.h>
1818

19+
#include "tkinter.h"
20+
21+
#ifdef TKINTER_PROTECT_LOADTK
22+
/* See Tkapp_TkInit in _tkinter.c for the usage of tk_load_faile */
23+
static int tk_load_failed;
24+
#endif
25+
1926
int
2027
Tcl_AppInit(Tcl_Interp *interp)
2128
{
2229
Tk_Window main_window;
23-
const char * _tkinter_skip_tk_init;
30+
const char *_tkinter_skip_tk_init;
31+
#ifdef TKINTER_PROTECT_LOADTK
32+
const char *_tkinter_tk_failed;
33+
#endif
2434

2535
#ifdef TK_AQUA
2636
#ifndef MAX_PATH_LEN
@@ -74,12 +84,32 @@ Tcl_AppInit(Tcl_Interp *interp)
7484
/* Initialize modules that don't require Tk */
7585
#endif
7686

77-
_tkinter_skip_tk_init = Tcl_GetVar(interp, "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
78-
if (_tkinter_skip_tk_init != NULL && strcmp(_tkinter_skip_tk_init, "1") == 0) {
87+
_tkinter_skip_tk_init = Tcl_GetVar(interp,
88+
"_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
89+
if (_tkinter_skip_tk_init != NULL &&
90+
strcmp(_tkinter_skip_tk_init, "1") == 0) {
7991
return TCL_OK;
8092
}
81-
if (Tk_Init(interp) == TCL_ERROR)
93+
94+
#ifdef TKINTER_PROTECT_LOADTK
95+
_tkinter_tk_failed = Tcl_GetVar(interp,
96+
"_tkinter_tk_failed", TCL_GLOBAL_ONLY);
97+
98+
if (tk_load_failed || (
99+
_tkinter_tk_failed != NULL &&
100+
strcmp(_tkinter_tk_failed, "1") == 0)) {
101+
Tcl_SetResult(interp, TKINTER_LOADTK_ERRMSG, TCL_STATIC);
102+
return TCL_ERROR;
103+
}
104+
#endif
105+
106+
if (Tk_Init(interp) == TCL_ERROR) {
107+
#ifdef TKINTER_PROTECT_LOADTK
108+
tk_load_failed = 1;
109+
Tcl_SetVar(interp, "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
110+
#endif
82111
return TCL_ERROR;
112+
}
83113

84114
main_window = Tk_MainWindow(interp);
85115

0 commit comments

Comments
 (0)