]> granicus.if.org Git - python/commitdiff
Issue #1731706: Call Tcl_ConditionFinalize for Tcl_Conditions that will
authorGuilherme Polo <ggpolo@gmail.com>
Fri, 6 Feb 2009 22:48:07 +0000 (22:48 +0000)
committerGuilherme Polo <ggpolo@gmail.com>
Fri, 6 Feb 2009 22:48:07 +0000 (22:48 +0000)
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.

Misc/NEWS
Modules/_tkinter.c

index 3c86cf230578b6cc37374408927fc343e0e181fc..96256f523ea81df00ee886a1fc0915bdd4af33d5 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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.
index 79fa6327ae3ad983b6bb111bfef039919e42ea87..5b1de8c7a30d2aecdd2920f648c389624f7f89db 100644 (file)
@@ -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