Kaydet (Commit) 363161a4 authored tarafından Guilherme Polo's avatar Guilherme Polo

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.
üst 14ff18d2
...@@ -149,9 +149,10 @@ Core and Builtins ...@@ -149,9 +149,10 @@ Core and Builtins
Library Library
------- -------
- Partial fix to issue #1731706: memory leak in Tkapp_Call when calling - Issue #1731706: Call Tcl_ConditionFinalize for Tcl_Conditions that will
from a thread different than the one that created the Tcl interpreter. not be used again (this requires Tcl/Tk 8.3.1), also fix a memory leak in
Patch by Robert Hancock. Tkapp_Call when calling from a thread different than the one that created
the Tcl interpreter. Patch by Robert Hancock.
- Issue #1520877: Now distutils.sysconfig reads $AR from the - Issue #1520877: Now distutils.sysconfig reads $AR from the
environment/Makefile. Patch by Douglas Greiman. environment/Makefile. Patch by Douglas Greiman.
......
...@@ -9,9 +9,9 @@ Copyright (C) 1994 Steen Lumholt. ...@@ -9,9 +9,9 @@ Copyright (C) 1994 Steen Lumholt.
/* TCL/TK VERSION INFO: /* TCL/TK VERSION INFO:
Only Tcl/Tk 8.2 and later are supported. Older versions are not Only Tcl/Tk 8.3.1 and later are supported. Older versions are not
supported. (Use Python 2.2 if you cannot upgrade your Tcl/Tk supported. Use Python 2.6 or older if you cannot upgrade your
libraries.) Tcl/Tk libraries.
*/ */
/* XXX Further speed-up ideas, involving Tcl 8.0 features: /* XXX Further speed-up ideas, involving Tcl 8.0 features:
...@@ -1110,7 +1110,7 @@ typedef struct Tkapp_CallEvent { ...@@ -1110,7 +1110,7 @@ typedef struct Tkapp_CallEvent {
int flags; int flags;
PyObject **res; PyObject **res;
PyObject **exc_type, **exc_value, **exc_tb; PyObject **exc_type, **exc_value, **exc_tb;
Tcl_Condition done; Tcl_Condition *done;
} Tkapp_CallEvent; } Tkapp_CallEvent;
void void
...@@ -1261,7 +1261,7 @@ Tkapp_CallProc(Tkapp_CallEvent *e, int flags) ...@@ -1261,7 +1261,7 @@ Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
done: done:
/* Wake up calling thread. */ /* Wake up calling thread. */
Tcl_MutexLock(&call_mutex); Tcl_MutexLock(&call_mutex);
Tcl_ConditionNotify(&e->done); Tcl_ConditionNotify(e->done);
Tcl_MutexUnlock(&call_mutex); Tcl_MutexUnlock(&call_mutex);
return 1; return 1;
} }
...@@ -1299,6 +1299,7 @@ Tkapp_Call(PyObject *selfptr, PyObject *args) ...@@ -1299,6 +1299,7 @@ Tkapp_Call(PyObject *selfptr, PyObject *args)
/* We cannot call the command directly. Instead, we must /* We cannot call the command directly. Instead, we must
marshal the parameters to the interpreter thread. */ marshal the parameters to the interpreter thread. */
Tkapp_CallEvent *ev; Tkapp_CallEvent *ev;
Tcl_Condition cond = NULL;
PyObject *exc_type, *exc_value, *exc_tb; PyObject *exc_type, *exc_value, *exc_tb;
if (!WaitForMainloop(self)) if (!WaitForMainloop(self))
return NULL; return NULL;
...@@ -1310,9 +1311,9 @@ Tkapp_Call(PyObject *selfptr, PyObject *args) ...@@ -1310,9 +1311,9 @@ Tkapp_Call(PyObject *selfptr, PyObject *args)
ev->exc_type = &exc_type; ev->exc_type = &exc_type;
ev->exc_value = &exc_value; ev->exc_value = &exc_value;
ev->exc_tb = &exc_tb; ev->exc_tb = &exc_tb;
ev->done = (Tcl_Condition)0; ev->done = &cond;
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex); Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
if (res == NULL) { if (res == NULL) {
if (exc_type) if (exc_type)
...@@ -1320,6 +1321,7 @@ Tkapp_Call(PyObject *selfptr, PyObject *args) ...@@ -1320,6 +1321,7 @@ Tkapp_Call(PyObject *selfptr, PyObject *args)
else else
PyErr_SetObject(Tkinter_TclError, exc_value); PyErr_SetObject(Tkinter_TclError, exc_value);
} }
Tcl_ConditionFinalize(&cond);
} }
else else
#endif #endif
...@@ -1505,7 +1507,7 @@ typedef struct VarEvent { ...@@ -1505,7 +1507,7 @@ typedef struct VarEvent {
PyObject **res; PyObject **res;
PyObject **exc_type; PyObject **exc_type;
PyObject **exc_val; PyObject **exc_val;
Tcl_Condition cond; Tcl_Condition *cond;
} VarEvent; } VarEvent;
static int static int
...@@ -1545,7 +1547,7 @@ var_proc(VarEvent* ev, int flags) ...@@ -1545,7 +1547,7 @@ var_proc(VarEvent* ev, int flags)
ENTER_PYTHON ENTER_PYTHON
var_perform(ev); var_perform(ev);
Tcl_MutexLock(&var_mutex); Tcl_MutexLock(&var_mutex);
Tcl_ConditionNotify(&ev->cond); Tcl_ConditionNotify(ev->cond);
Tcl_MutexUnlock(&var_mutex); Tcl_MutexUnlock(&var_mutex);
LEAVE_PYTHON LEAVE_PYTHON
return 1; return 1;
...@@ -1560,6 +1562,7 @@ var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags) ...@@ -1560,6 +1562,7 @@ var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
TkappObject *self = (TkappObject*)selfptr; TkappObject *self = (TkappObject*)selfptr;
VarEvent *ev; VarEvent *ev;
PyObject *res, *exc_type, *exc_val; PyObject *res, *exc_type, *exc_val;
Tcl_Condition cond = NULL;
/* The current thread is not the interpreter thread. Marshal /* The current thread is not the interpreter thread. Marshal
the call to the interpreter thread, then wait for the call to the interpreter thread, then wait for
...@@ -1576,9 +1579,10 @@ var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags) ...@@ -1576,9 +1579,10 @@ var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
ev->res = &res; ev->res = &res;
ev->exc_type = &exc_type; ev->exc_type = &exc_type;
ev->exc_val = &exc_val; ev->exc_val = &exc_val;
ev->cond = NULL; ev->cond = &cond;
ev->ev.proc = (Tcl_EventProc*)var_proc; ev->ev.proc = (Tcl_EventProc*)var_proc;
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex); Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
Tcl_ConditionFinalize(&cond);
if (!res) { if (!res) {
PyErr_SetObject(exc_type, exc_val); PyErr_SetObject(exc_type, exc_val);
Py_DECREF(exc_type); Py_DECREF(exc_type);
...@@ -2065,7 +2069,7 @@ typedef struct CommandEvent{ ...@@ -2065,7 +2069,7 @@ typedef struct CommandEvent{
int create; int create;
int *status; int *status;
ClientData *data; ClientData *data;
Tcl_Condition done; Tcl_Condition *done;
} CommandEvent; } CommandEvent;
static int static int
...@@ -2078,7 +2082,7 @@ Tkapp_CommandProc(CommandEvent *ev, int flags) ...@@ -2078,7 +2082,7 @@ Tkapp_CommandProc(CommandEvent *ev, int flags)
else else
*ev->status = Tcl_DeleteCommand(ev->interp, ev->name); *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
Tcl_MutexLock(&command_mutex); Tcl_MutexLock(&command_mutex);
Tcl_ConditionNotify(&ev->done); Tcl_ConditionNotify(ev->done);
Tcl_MutexUnlock(&command_mutex); Tcl_MutexUnlock(&command_mutex);
return 1; return 1;
} }
...@@ -2114,6 +2118,7 @@ Tkapp_CreateCommand(PyObject *selfptr, PyObject *args) ...@@ -2114,6 +2118,7 @@ Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
data->func = func; data->func = func;
if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) { if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Tcl_Condition cond = NULL;
CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent)); CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc; ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
ev->interp = self->interp; ev->interp = self->interp;
...@@ -2121,8 +2126,9 @@ Tkapp_CreateCommand(PyObject *selfptr, PyObject *args) ...@@ -2121,8 +2126,9 @@ Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
ev->name = cmdName; ev->name = cmdName;
ev->data = (ClientData)data; ev->data = (ClientData)data;
ev->status = &err; ev->status = &err;
ev->done = NULL; ev->done = &cond;
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex); Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
Tcl_ConditionFinalize(&cond);
} }
else { else {
ENTER_TCL ENTER_TCL
...@@ -2153,6 +2159,7 @@ Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args) ...@@ -2153,6 +2159,7 @@ Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName)) if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
return NULL; return NULL;
if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) { if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Tcl_Condition cond = NULL;
CommandEvent *ev; CommandEvent *ev;
ev = (CommandEvent*)ckalloc(sizeof(CommandEvent)); ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc; ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
...@@ -2160,9 +2167,10 @@ Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args) ...@@ -2160,9 +2167,10 @@ Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
ev->create = 0; ev->create = 0;
ev->name = cmdName; ev->name = cmdName;
ev->status = &err; ev->status = &err;
ev->done = NULL; ev->done = &cond;
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
&command_mutex); &command_mutex);
Tcl_ConditionFinalize(&cond);
} }
else { else {
ENTER_TCL ENTER_TCL
......
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