Commit b681df49 authored by Guilherme Polo's avatar Guilherme Polo

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.
........
parent c1761b7c
...@@ -163,6 +163,9 @@ Core and Builtins ...@@ -163,6 +163,9 @@ Core and Builtins
Library 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 #4890: Handle empty text search pattern in Tkinter.Text.search.
- Issue #4512 (part 2): Promote ``ZipImporter._get_filename()`` to be a - Issue #4512 (part 2): Promote ``ZipImporter._get_filename()`` to be a
......
...@@ -33,6 +33,8 @@ Copyright (C) 1994 Steen Lumholt. ...@@ -33,6 +33,8 @@ Copyright (C) 1994 Steen Lumholt.
#include <windows.h> #include <windows.h>
#endif #endif
#include "tkinter.h"
/* Allow using this code in Python 2.[12] */ /* Allow using this code in Python 2.[12] */
#ifndef PyDoc_STRVAR #ifndef PyDoc_STRVAR
#define PyDoc_STRVAR(name,str) static char name[] = str #define PyDoc_STRVAR(name,str) static char name[] = str
...@@ -74,9 +76,7 @@ Copyright (C) 1994 Steen Lumholt. ...@@ -74,9 +76,7 @@ Copyright (C) 1994 Steen Lumholt.
#define CONST #define CONST
#endif #endif
#define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION) #if TK_VERSION_HEX < 0x08020002
#if TKMAJORMINOR < 8002
#error "Tk older than 8.2 not supported" #error "Tk older than 8.2 not supported"
#endif #endif
...@@ -280,6 +280,9 @@ static PyObject *excInCmd; ...@@ -280,6 +280,9 @@ static PyObject *excInCmd;
static PyObject *valInCmd; static PyObject *valInCmd;
static PyObject *trbInCmd; static PyObject *trbInCmd;
#ifdef TKINTER_PROTECT_LOADTK
static int tk_load_failed;
#endif
static PyObject * static PyObject *
...@@ -553,21 +556,35 @@ SplitObj(PyObject *arg) ...@@ -553,21 +556,35 @@ SplitObj(PyObject *arg)
int int
Tcl_AppInit(Tcl_Interp *interp) Tcl_AppInit(Tcl_Interp *interp)
{ {
Tk_Window main;
const char * _tkinter_skip_tk_init; const char * _tkinter_skip_tk_init;
if (Tcl_Init(interp) == TCL_ERROR) { if (Tcl_Init(interp) == TCL_ERROR) {
PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp)); PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
return TCL_ERROR; 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) { _tkinter_skip_tk_init = Tcl_GetVar(interp,
main = Tk_MainWindow(interp); "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
if (Tk_Init(interp) == TCL_ERROR) { if (_tkinter_skip_tk_init != NULL &&
PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp)); strcmp(_tkinter_skip_tk_init, "1") == 0) {
return TCL_ERROR; 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; return TCL_OK;
} }
#endif /* !WITH_APPINIT */ #endif /* !WITH_APPINIT */
...@@ -650,8 +667,15 @@ Tkapp_New(char *screenName, char *className, ...@@ -650,8 +667,15 @@ Tkapp_New(char *screenName, char *className,
ckfree(argv0); ckfree(argv0);
if (! wantTk) { 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 */ /* some initial arguments need to be in argv */
if (sync || use) { if (sync || use) {
...@@ -686,6 +710,18 @@ Tkapp_New(char *screenName, char *className, ...@@ -686,6 +710,18 @@ Tkapp_New(char *screenName, char *className,
if (Tcl_AppInit(v->interp) != TCL_OK) { if (Tcl_AppInit(v->interp) != TCL_OK) {
PyObject *result = Tkinter_Error((PyObject *)v); 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); Py_DECREF((PyObject *)v);
return (TkappObject *)result; return (TkappObject *)result;
} }
...@@ -2547,22 +2583,21 @@ Tkapp_InterpAddr(PyObject *self, PyObject *args) ...@@ -2547,22 +2583,21 @@ Tkapp_InterpAddr(PyObject *self, PyObject *args)
static PyObject * static PyObject *
Tkapp_TkInit(PyObject *self, PyObject *args) Tkapp_TkInit(PyObject *self, PyObject *args)
{ {
static int has_failed;
Tcl_Interp *interp = Tkapp_Interp(self); Tcl_Interp *interp = Tkapp_Interp(self);
Tk_Window main_window;
const char * _tk_exists = NULL; const char * _tk_exists = NULL;
int err; int err;
main_window = Tk_MainWindow(interp);
#ifdef TKINTER_PROTECT_LOADTK
/* In all current versions of Tk (including 8.4.13), Tk_Init /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
deadlocks on the second call when the first call failed. * first call failed.
To avoid the deadlock, we just refuse the second call through * To avoid the deadlock, we just refuse the second call through
a static variable. */ * a static variable.
if (has_failed) { */
PyErr_SetString(Tkinter_TclError, if (tk_load_failed) {
"Calling Tk_Init again after a previous call failed might deadlock"); PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
return NULL; return NULL;
} }
#endif
/* We want to guard against calling Tk_Init() multiple times */ /* We want to guard against calling Tk_Init() multiple times */
CHECK_TCL_APPARTMENT; CHECK_TCL_APPARTMENT;
...@@ -2582,8 +2617,10 @@ Tkapp_TkInit(PyObject *self, PyObject *args) ...@@ -2582,8 +2617,10 @@ Tkapp_TkInit(PyObject *self, PyObject *args)
} }
if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) { if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
if (Tk_Init(interp) == TCL_ERROR) { if (Tk_Init(interp) == TCL_ERROR) {
PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self))); PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
has_failed = 1; #ifdef TKINTER_PROTECT_LOADTK
tk_load_failed = 1;
#endif
return NULL; return NULL;
} }
} }
......
...@@ -16,11 +16,21 @@ ...@@ -16,11 +16,21 @@
#include <tcl.h> #include <tcl.h>
#include <tk.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 int
Tcl_AppInit(Tcl_Interp *interp) Tcl_AppInit(Tcl_Interp *interp)
{ {
Tk_Window main_window; 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 #ifdef TK_AQUA
#ifndef MAX_PATH_LEN #ifndef MAX_PATH_LEN
...@@ -74,12 +84,32 @@ Tcl_AppInit(Tcl_Interp *interp) ...@@ -74,12 +84,32 @@ Tcl_AppInit(Tcl_Interp *interp)
/* Initialize modules that don't require Tk */ /* Initialize modules that don't require Tk */
#endif #endif
_tkinter_skip_tk_init = Tcl_GetVar(interp, "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY); _tkinter_skip_tk_init = Tcl_GetVar(interp,
if (_tkinter_skip_tk_init != NULL && strcmp(_tkinter_skip_tk_init, "1") == 0) { "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
if (_tkinter_skip_tk_init != NULL &&
strcmp(_tkinter_skip_tk_init, "1") == 0) {
return TCL_OK; 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; return TCL_ERROR;
}
main_window = Tk_MainWindow(interp); main_window = Tk_MainWindow(interp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment