Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 491aee2

Browse files
committed
Merged revisions 69376-69377 via svnmerge from
svn+ssh://pythondev/python/trunk ........ r69376 | guilherme.polo | 2009-02-06 20:26:22 -0200 (Fri, 06 Feb 2009) | 3 lines Partial fix to issue #1731706: memory leak in Tkapp_Call when calling from a thread different than the one that created the Tcl interpreter. ........ r69377 | guilherme.polo | 2009-02-06 20:48:07 -0200 (Fri, 06 Feb 2009) | 5 lines 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. ........
1 parent b41bc91 commit 491aee2

2 files changed

Lines changed: 33 additions & 18 deletions

File tree

Misc/NEWS

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,11 @@ Core and Builtins
155155
Library
156156
-------
157157

158+
- Issue #1731706: Call Tcl_ConditionFinalize for Tcl_Conditions that will
159+
not be used again (this requires Tcl/Tk 8.3.1), also fix a memory leak in
160+
Tkapp_Call when calling from a thread different than the one that created
161+
the Tcl interpreter. Patch by Robert Hancock.
162+
158163
- Issue #4285: Change sys.version_info to be a named tuple. Patch by
159164
Ross Light.
160165

Modules/_tkinter.c

Lines changed: 28 additions & 18 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:
@@ -1085,7 +1085,7 @@ typedef struct Tkapp_CallEvent {
10851085
int flags;
10861086
PyObject **res;
10871087
PyObject **exc_type, **exc_value, **exc_tb;
1088-
Tcl_Condition done;
1088+
Tcl_Condition *done;
10891089
} Tkapp_CallEvent;
10901090

10911091
void
@@ -1208,10 +1208,12 @@ Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
12081208
*(e->res) = Tkapp_CallResult(e->self);
12091209
}
12101210
LEAVE_PYTHON
1211-
done:
1211+
1212+
Tkapp_CallDeallocArgs(objv, objStore, objc);
1213+
done:
12121214
/* Wake up calling thread. */
12131215
Tcl_MutexLock(&call_mutex);
1214-
Tcl_ConditionNotify(&e->done);
1216+
Tcl_ConditionNotify(e->done);
12151217
Tcl_MutexUnlock(&call_mutex);
12161218
return 1;
12171219
}
@@ -1249,6 +1251,7 @@ Tkapp_Call(PyObject *selfptr, PyObject *args)
12491251
/* We cannot call the command directly. Instead, we must
12501252
marshal the parameters to the interpreter thread. */
12511253
Tkapp_CallEvent *ev;
1254+
Tcl_Condition cond = NULL;
12521255
PyObject *exc_type, *exc_value, *exc_tb;
12531256
if (!WaitForMainloop(self))
12541257
return NULL;
@@ -1260,16 +1263,17 @@ Tkapp_Call(PyObject *selfptr, PyObject *args)
12601263
ev->exc_type = &exc_type;
12611264
ev->exc_value = &exc_value;
12621265
ev->exc_tb = &exc_tb;
1263-
ev->done = (Tcl_Condition)0;
1266+
ev->done = &cond;
12641267

1265-
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1268+
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
12661269

12671270
if (res == NULL) {
12681271
if (exc_type)
12691272
PyErr_Restore(exc_type, exc_value, exc_tb);
12701273
else
12711274
PyErr_SetObject(Tkinter_TclError, exc_value);
12721275
}
1276+
Tcl_ConditionFinalize(&cond);
12731277
}
12741278
else
12751279
#endif
@@ -1455,7 +1459,7 @@ typedef struct VarEvent {
14551459
PyObject **res;
14561460
PyObject **exc_type;
14571461
PyObject **exc_val;
1458-
Tcl_Condition cond;
1462+
Tcl_Condition *cond;
14591463
} VarEvent;
14601464

14611465
static int
@@ -1499,7 +1503,7 @@ var_proc(VarEvent* ev, int flags)
14991503
ENTER_PYTHON
15001504
var_perform(ev);
15011505
Tcl_MutexLock(&var_mutex);
1502-
Tcl_ConditionNotify(&ev->cond);
1506+
Tcl_ConditionNotify(ev->cond);
15031507
Tcl_MutexUnlock(&var_mutex);
15041508
LEAVE_PYTHON
15051509
return 1;
@@ -1514,6 +1518,7 @@ var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
15141518
TkappObject *self = (TkappObject*)selfptr;
15151519
VarEvent *ev;
15161520
PyObject *res, *exc_type, *exc_val;
1521+
Tcl_Condition cond = NULL;
15171522

15181523
/* The current thread is not the interpreter thread. Marshal
15191524
the call to the interpreter thread, then wait for
@@ -1530,9 +1535,10 @@ var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
15301535
ev->res = &res;
15311536
ev->exc_type = &exc_type;
15321537
ev->exc_val = &exc_val;
1533-
ev->cond = NULL;
1538+
ev->cond = &cond;
15341539
ev->ev.proc = (Tcl_EventProc*)var_proc;
1535-
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
1540+
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1541+
Tcl_ConditionFinalize(&cond);
15361542
if (!res) {
15371543
PyErr_SetObject(exc_type, exc_val);
15381544
Py_DECREF(exc_type);
@@ -2019,7 +2025,7 @@ typedef struct CommandEvent{
20192025
int create;
20202026
int *status;
20212027
ClientData *data;
2022-
Tcl_Condition done;
2028+
Tcl_Condition *done;
20232029
} CommandEvent;
20242030

20252031
static int
@@ -2032,7 +2038,7 @@ Tkapp_CommandProc(CommandEvent *ev, int flags)
20322038
else
20332039
*ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
20342040
Tcl_MutexLock(&command_mutex);
2035-
Tcl_ConditionNotify(&ev->done);
2041+
Tcl_ConditionNotify(ev->done);
20362042
Tcl_MutexUnlock(&command_mutex);
20372043
return 1;
20382044
}
@@ -2068,15 +2074,17 @@ Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
20682074
data->func = func;
20692075

20702076
if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2077+
Tcl_Condition cond = NULL;
20712078
CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
20722079
ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
20732080
ev->interp = self->interp;
20742081
ev->create = 1;
20752082
ev->name = cmdName;
20762083
ev->data = (ClientData)data;
20772084
ev->status = &err;
2078-
ev->done = NULL;
2079-
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2085+
ev->done = &cond;
2086+
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2087+
Tcl_ConditionFinalize(&cond);
20802088
}
20812089
else {
20822090
ENTER_TCL
@@ -2107,16 +2115,18 @@ Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
21072115
if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
21082116
return NULL;
21092117
if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2118+
Tcl_Condition cond = NULL;
21102119
CommandEvent *ev;
21112120
ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
21122121
ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
21132122
ev->interp = self->interp;
21142123
ev->create = 0;
21152124
ev->name = cmdName;
21162125
ev->status = &err;
2117-
ev->done = NULL;
2118-
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2126+
ev->done = &cond;
2127+
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
21192128
&command_mutex);
2129+
Tcl_ConditionFinalize(&cond);
21202130
}
21212131
else {
21222132
ENTER_TCL

0 commit comments

Comments
 (0)