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