diff options
author | Guilherme Polo <ggpolo@gmail.com> | 2009-02-09 22:33:59 (GMT) |
---|---|---|
committer | Guilherme Polo <ggpolo@gmail.com> | 2009-02-09 22:33:59 (GMT) |
commit | b681df490ba2a06b0655e712d24f79110a41aefb (patch) | |
tree | 32f45b85773ea88a4bbe9df4730d040d12c180d9 /Modules/_tkinter.c | |
parent | c1761b7cd59b8179adbd9f35bee3847f5dba1f8d (diff) | |
download | cpython-b681df490ba2a06b0655e712d24f79110a41aefb.zip cpython-b681df490ba2a06b0655e712d24f79110a41aefb.tar.gz cpython-b681df490ba2a06b0655e712d24f79110a41aefb.tar.bz2 |
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.
........
Diffstat (limited to 'Modules/_tkinter.c')
-rw-r--r-- | Modules/_tkinter.c | 87 |
1 files changed, 62 insertions, 25 deletions
diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c index 645f984..1f5a470 100644 --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -33,6 +33,8 @@ Copyright (C) 1994 Steen Lumholt. #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 @@ Copyright (C) 1994 Steen Lumholt. #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 *excInCmd; static PyObject *valInCmd; static PyObject *trbInCmd; +#ifdef TKINTER_PROTECT_LOADTK +static int tk_load_failed; +#endif static PyObject * @@ -553,21 +556,35 @@ SplitObj(PyObject *arg) 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 @@ Tkapp_New(char *screenName, char *className, 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 @@ Tkapp_New(char *screenName, char *className, 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 @@ 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; 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 @@ 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; + PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self))); +#ifdef TKINTER_PROTECT_LOADTK + tk_load_failed = 1; +#endif return NULL; } } |