Skip to content

Commit c2bb7ce

Browse files
author
guilherme.polo
committed
Issue #1731706: Call Tcl_ConditionFinalize for Tcl_Conditions that will
not be used again (this requires Tcl/Tk 8.3.1), also fix a memory leak in Tkapp_Call when calling from a thread different than the one that created the Tcl interpreter. git-svn-id: http://svn.python.org/projects/python/trunk@69377 6015fed2-1504-0410-9fe1-9d1591cc4771
1 parent 3465b36 commit c2bb7ce

File tree

2 files changed

+29
-20
lines changed

2 files changed

+29
-20
lines changed

Misc/NEWS

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,10 @@ Core and Builtins
149149
Library
150150
-------
151151

152-
- Partial fix to issue #1731706: memory leak in Tkapp_Call when calling
153-
from a thread different than the one that created the Tcl interpreter.
154-
Patch by Robert Hancock.
152+
- Issue #1731706: Call Tcl_ConditionFinalize for Tcl_Conditions that will
153+
not be used again (this requires Tcl/Tk 8.3.1), also fix a memory leak in
154+
Tkapp_Call when calling from a thread different than the one that created
155+
the Tcl interpreter. Patch by Robert Hancock.
155156

156157
- Issue #1520877: Now distutils.sysconfig reads $AR from the
157158
environment/Makefile. Patch by Douglas Greiman.

Modules/_tkinter.c

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ Copyright (C) 1994 Steen Lumholt.
99

1010
/* TCL/TK VERSION INFO:
1111
12-
Only Tcl/Tk 8.2 and later are supported. Older versions are not
13-
supported. (Use Python 2.2 if you cannot upgrade your Tcl/Tk
14-
libraries.)
12+
Only Tcl/Tk 8.3.1 and later are supported. Older versions are not
13+
supported. Use Python 2.6 or older if you cannot upgrade your
14+
Tcl/Tk libraries.
1515
*/
1616

1717
/* XXX Further speed-up ideas, involving Tcl 8.0 features:
@@ -1110,7 +1110,7 @@ typedef struct Tkapp_CallEvent {
11101110
int flags;
11111111
PyObject **res;
11121112
PyObject **exc_type, **exc_value, **exc_tb;
1113-
Tcl_Condition done;
1113+
Tcl_Condition *done;
11141114
} Tkapp_CallEvent;
11151115

11161116
void
@@ -1261,7 +1261,7 @@ Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
12611261
done:
12621262
/* Wake up calling thread. */
12631263
Tcl_MutexLock(&call_mutex);
1264-
Tcl_ConditionNotify(&e->done);
1264+
Tcl_ConditionNotify(e->done);
12651265
Tcl_MutexUnlock(&call_mutex);
12661266
return 1;
12671267
}
@@ -1299,6 +1299,7 @@ Tkapp_Call(PyObject *selfptr, PyObject *args)
12991299
/* We cannot call the command directly. Instead, we must
13001300
marshal the parameters to the interpreter thread. */
13011301
Tkapp_CallEvent *ev;
1302+
Tcl_Condition cond = NULL;
13021303
PyObject *exc_type, *exc_value, *exc_tb;
13031304
if (!WaitForMainloop(self))
13041305
return NULL;
@@ -1310,16 +1311,17 @@ Tkapp_Call(PyObject *selfptr, PyObject *args)
13101311
ev->exc_type = &exc_type;
13111312
ev->exc_value = &exc_value;
13121313
ev->exc_tb = &exc_tb;
1313-
ev->done = (Tcl_Condition)0;
1314+
ev->done = &cond;
13141315

1315-
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1316+
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
13161317

13171318
if (res == NULL) {
13181319
if (exc_type)
13191320
PyErr_Restore(exc_type, exc_value, exc_tb);
13201321
else
13211322
PyErr_SetObject(Tkinter_TclError, exc_value);
13221323
}
1324+
Tcl_ConditionFinalize(&cond);
13231325
}
13241326
else
13251327
#endif
@@ -1505,7 +1507,7 @@ typedef struct VarEvent {
15051507
PyObject **res;
15061508
PyObject **exc_type;
15071509
PyObject **exc_val;
1508-
Tcl_Condition cond;
1510+
Tcl_Condition *cond;
15091511
} VarEvent;
15101512

15111513
static int
@@ -1545,7 +1547,7 @@ var_proc(VarEvent* ev, int flags)
15451547
ENTER_PYTHON
15461548
var_perform(ev);
15471549
Tcl_MutexLock(&var_mutex);
1548-
Tcl_ConditionNotify(&ev->cond);
1550+
Tcl_ConditionNotify(ev->cond);
15491551
Tcl_MutexUnlock(&var_mutex);
15501552
LEAVE_PYTHON
15511553
return 1;
@@ -1560,6 +1562,7 @@ var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
15601562
TkappObject *self = (TkappObject*)selfptr;
15611563
VarEvent *ev;
15621564
PyObject *res, *exc_type, *exc_val;
1565+
Tcl_Condition cond = NULL;
15631566

15641567
/* The current thread is not the interpreter thread. Marshal
15651568
the call to the interpreter thread, then wait for
@@ -1576,9 +1579,10 @@ var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
15761579
ev->res = &res;
15771580
ev->exc_type = &exc_type;
15781581
ev->exc_val = &exc_val;
1579-
ev->cond = NULL;
1582+
ev->cond = &cond;
15801583
ev->ev.proc = (Tcl_EventProc*)var_proc;
1581-
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
1584+
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1585+
Tcl_ConditionFinalize(&cond);
15821586
if (!res) {
15831587
PyErr_SetObject(exc_type, exc_val);
15841588
Py_DECREF(exc_type);
@@ -2065,7 +2069,7 @@ typedef struct CommandEvent{
20652069
int create;
20662070
int *status;
20672071
ClientData *data;
2068-
Tcl_Condition done;
2072+
Tcl_Condition *done;
20692073
} CommandEvent;
20702074

20712075
static int
@@ -2078,7 +2082,7 @@ Tkapp_CommandProc(CommandEvent *ev, int flags)
20782082
else
20792083
*ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
20802084
Tcl_MutexLock(&command_mutex);
2081-
Tcl_ConditionNotify(&ev->done);
2085+
Tcl_ConditionNotify(ev->done);
20822086
Tcl_MutexUnlock(&command_mutex);
20832087
return 1;
20842088
}
@@ -2114,15 +2118,17 @@ Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
21142118
data->func = func;
21152119

21162120
if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2121+
Tcl_Condition cond = NULL;
21172122
CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
21182123
ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
21192124
ev->interp = self->interp;
21202125
ev->create = 1;
21212126
ev->name = cmdName;
21222127
ev->data = (ClientData)data;
21232128
ev->status = &err;
2124-
ev->done = NULL;
2125-
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2129+
ev->done = &cond;
2130+
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2131+
Tcl_ConditionFinalize(&cond);
21262132
}
21272133
else {
21282134
ENTER_TCL
@@ -2153,16 +2159,18 @@ Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
21532159
if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
21542160
return NULL;
21552161
if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2162+
Tcl_Condition cond = NULL;
21562163
CommandEvent *ev;
21572164
ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
21582165
ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
21592166
ev->interp = self->interp;
21602167
ev->create = 0;
21612168
ev->name = cmdName;
21622169
ev->status = &err;
2163-
ev->done = NULL;
2164-
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2170+
ev->done = &cond;
2171+
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
21652172
&command_mutex);
2173+
Tcl_ConditionFinalize(&cond);
21662174
}
21672175
else {
21682176
ENTER_TCL

0 commit comments

Comments
 (0)