Skip to content

Commit f73ddd2

Browse files
Michiel Jan Laurens de HoonMichiel Jan Laurens de Hoon
authored andcommitted
Check if Tcl is threaded when creating a tkapp
1 parent da2785d commit f73ddd2

2 files changed

Lines changed: 22 additions & 23 deletions

File tree

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
Require that Tcl is always built with thread support.
1+
Require that Tcl is always built with thread support.
22
This requirement only affects Tcl 8.x, as Tcl 9.x is always thread-enabled.

‎Modules/_tkinter.c‎

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ Copyright (C) 1994 Steen Lumholt.
4343
/* As we require that Tcl is compiled for threads, we must also define
4444
TCL_THREADS. We define it always; if Tcl is not threaded, the thread
4545
functions in Tcl are empty. We check if Tcl is actually compiled for
46-
threads when importing this module. */
46+
threads when creating a tkapp. */
4747
#define TCL_THREADS
4848

4949
#ifdef TK_FRAMEWORK
@@ -283,23 +283,6 @@ Tkinter_TkInit(Tcl_Interp *interp)
283283
284284
*/
285285

286-
#if TCL_MAJOR_VERSION < 9 /* Tcl 9.x is always threaded */
287-
static int
288-
_check_tcl_threaded(void)
289-
{
290-
Tcl_Interp* interp;
291-
Tcl_Obj* threaded;
292-
interp = Tcl_CreateInterp();
293-
threaded = Tcl_GetVar2Ex(interp,
294-
"tcl_platform",
295-
"threaded",
296-
TCL_GLOBAL_ONLY);
297-
Tcl_DeleteInterp(interp);
298-
if (threaded == NULL) return 0;
299-
else return 1;
300-
}
301-
#endif
302-
303286
static Tcl_ThreadDataKey state_key;
304287
#define tcl_tstate \
305288
(*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
@@ -633,13 +616,30 @@ Tkapp_New(const char *screenName, const char *className,
633616
{
634617
TkappObject *v;
635618
char *argv0;
619+
#if TCL_MAJOR_VERSION < 9 /* Tcl 9.x is always threaded */
620+
static Tcl_Obj* threaded = NULL;
621+
#endif
636622

637623
PyTypeObject *tp = (PyTypeObject *)Tkapp_Type;
638624
v = (TkappObject *)tp->tp_alloc(tp, 0);
639625
if (v == NULL)
640626
return NULL;
641627

642628
v->interp = Tcl_CreateInterp();
629+
#if TCL_MAJOR_VERSION < 9 /* Tcl 9.x is always threaded */
630+
if (threaded == NULL) {
631+
threaded = Tcl_GetVar2Ex(v->interp,
632+
"tcl_platform",
633+
"threaded",
634+
TCL_GLOBAL_ONLY);
635+
if (threaded == NULL) {
636+
PyErr_SetString(PyExc_RuntimeError,
637+
"Tcl must be compiled with thread support");
638+
Py_DECREF(v);
639+
return NULL;
640+
}
641+
}
642+
#endif
643643
v->wantobjects = wantobjects;
644644
#if TCL_MAJOR_VERSION >= 9
645645
v->threaded = 1;
@@ -1645,10 +1645,9 @@ Tkapp_CallProc(Tcl_Event *evPtr, int flags)
16451645

16461646
/* This is the main entry point for calling a Tcl command.
16471647
It supports two cases, with regard to threading:
1648-
2. Caller of the command is in the interpreter thread:
1649-
Execute the command in the calling thread. Since the Tcl lock will
1650-
not be used, we can merge that with case 1.
1651-
3. Caller is in a different thread: Must queue an event to
1648+
1. Caller of the command is in the interpreter thread:
1649+
Execute the command in the calling thread.
1650+
2. Caller is in a different thread: Must queue an event to
16521651
the interpreter thread. Allocation of Tcl objects needs to occur in the
16531652
interpreter thread, so we ship the PyObject* args to the target thread,
16541653
and perform processing there. */

0 commit comments

Comments
 (0)