mirror of https://github.com/python/cpython.git
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. ........
This commit is contained in:
parent
c1761b7cd5
commit
b681df490b
|
@ -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.
|
||||||
#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.
|
||||||
#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;
|
||||||
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)
|
||||||
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,
|
||||||
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,
|
||||||
|
|
||||||
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)
|
||||||
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);
|
|
||||||
|
|
||||||
/* In all current versions of Tk (including 8.4.13), Tk_Init
|
#ifdef TKINTER_PROTECT_LOADTK
|
||||||
deadlocks on the second call when the first call failed.
|
/* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
|
||||||
To avoid the deadlock, we just refuse the second call through
|
* first call failed.
|
||||||
a static variable. */
|
* To avoid the deadlock, we just refuse the second call through
|
||||||
if (has_failed) {
|
* a static variable.
|
||||||
PyErr_SetString(Tkinter_TclError,
|
*/
|
||||||
"Calling Tk_Init again after a previous call failed might deadlock");
|
if (tk_load_failed) {
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
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 @@
|
||||||
#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)
|
||||||
/* 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;
|
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);
|
main_window = Tk_MainWindow(interp);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue