
For a while now, I've noticed test_tcl locking up when trying to refleaktest it. I was able to reproduce it quite simply: import Tkinter import os if "DISPLAY" in os.environ: del os.environ["DISPLAY"] tcl = Tkinter.Tcl() try: tcl.loadtk() except Exception, e: print e tcl.loadtk() Or, more directly, using _tkinter directly: import _tkinter import os if "DISPLAY" in os.environ: del os.environ["DISPLAY"] tk = _tkinter.create(None, "test", "Tk", 0, 1, 0) try: tk.loadtk() except: pass tk.loadtk() In either case, the second loadtk never finishes. It seems that, on my platform at least, Tk_Init() doesn't like being called twice even when the first call resulted in an error. That's Tcl and Tk 8.4.12. Tkapp_Init() (which is the Tkinter part that calls Tk_Init()) does its best to guard against calling Tk_Init() twice when the first call was succesful, but it doesn't remember failure cases. I don't know enough about Tcl/Tk or Tkinter how this is best handled, but it would be mightily convenient if it were. ;-) I've created a bugreport on it, and I hope someone with Tkinter knowledge can step in and fix it. (It looks like SF auto-assigned it to Martin already, hmm.) http://sourceforge.net/tracker/index.php?func=detail&aid=1475162&group_id=5470&atid=105470 -- Thomas Wouters <thomas@python.org> Hi! I'm a .signature virus! copy me into your .signature file to help me spread!

I just read the manpage for Tk_Init(3) (fc4 package tk-8.4.9-3) and it does not say that Tk_Init() may only be called once. While this doesn't mean Python shouldn't work around it, I think the behavior should be considered a bug in Tk, not _tkinter. However, on this system, I couldn't recreate the problem you reported with either the "using _tkinter directly" instructions, or using this "C" test program: #include <tcl.h> #include <tk.h> int main(void) { Tcl_Interp *trp; unsetenv("DISPLAY"); trp = Tcl_CreateInterp(); printf("%d\n", Tk_Init(trp)); printf("%d\n", Tk_Init(trp)); return 0; } Jeff

On 4/24/06, Jeff Epler <jepler@unpythonic.net> wrote:
FWIW, the Tk_Init manpage says "the Tk interpreter should not already be loaded", and it then goes on to say that if Tk_Init fails to *initialize* the interpreter, an error is returned. So it's unclear to me whether Tk_Init really "loads the interpreter", and whether it unloads after an error occurs (apparently not, I'd say ;) http://www.tcl.tk/man/tcl8.4/TkLib/Tk_Init.htm However, on this system, I couldn't recreate the problem you reported
Yes, this C snippet locks up on my systems, just as the python snippet does. -- Thomas Wouters <thomas@python.org> Hi! I'm a .signature virus! copy me into your .signature file to help me spread!

Jeff Epler wrote:
The problem only occurs when Tcl and Tk were compiled with --enable-threads, and it occurs because Tk fails to unlock a mutex in a few error cases. The patch below fixes the problem. I'll report it to the Tcl people, and see whether I can work around in _tkinter. Regards, Martin diff -ur tk8.4.13/generic/tkWindow.c tk8.4.13.modified/generic/tkWindow.c --- tk8.4.13/generic/tkWindow.c 2006-04-04 23:49:57.000000000 +0200 +++ tk8.4.13.modified/generic/tkWindow.c 2006-04-30 21:41:37.000000000 +0200 @@ -3108,6 +3108,7 @@ Tcl_DStringFree(&class); if (code != TCL_OK) { + Tcl_MutexUnlock(&windowMutex); goto done; } Tcl_ResetResult(interp); @@ -3124,6 +3125,7 @@ Tcl_SetVar(interp, "geometry", geometry, TCL_GLOBAL_ONLY); code = Tcl_VarEval(interp, "wm geometry . ", geometry, (char *) NULL); if (code != TCL_OK) { + Tcl_MutexUnlock(&windowMutex); goto done; } geometry = NULL;

Thomas Wouters wrote:
I have now reported the underlying Tk bug at http://sourceforge.net/tracker/index.php?func=detail&aid=1479587&group_id=12997&atid=112997 and worked around it in _tkinter.c. Regards, Martin

I just read the manpage for Tk_Init(3) (fc4 package tk-8.4.9-3) and it does not say that Tk_Init() may only be called once. While this doesn't mean Python shouldn't work around it, I think the behavior should be considered a bug in Tk, not _tkinter. However, on this system, I couldn't recreate the problem you reported with either the "using _tkinter directly" instructions, or using this "C" test program: #include <tcl.h> #include <tk.h> int main(void) { Tcl_Interp *trp; unsetenv("DISPLAY"); trp = Tcl_CreateInterp(); printf("%d\n", Tk_Init(trp)); printf("%d\n", Tk_Init(trp)); return 0; } Jeff

On 4/24/06, Jeff Epler <jepler@unpythonic.net> wrote:
FWIW, the Tk_Init manpage says "the Tk interpreter should not already be loaded", and it then goes on to say that if Tk_Init fails to *initialize* the interpreter, an error is returned. So it's unclear to me whether Tk_Init really "loads the interpreter", and whether it unloads after an error occurs (apparently not, I'd say ;) http://www.tcl.tk/man/tcl8.4/TkLib/Tk_Init.htm However, on this system, I couldn't recreate the problem you reported
Yes, this C snippet locks up on my systems, just as the python snippet does. -- Thomas Wouters <thomas@python.org> Hi! I'm a .signature virus! copy me into your .signature file to help me spread!

Jeff Epler wrote:
The problem only occurs when Tcl and Tk were compiled with --enable-threads, and it occurs because Tk fails to unlock a mutex in a few error cases. The patch below fixes the problem. I'll report it to the Tcl people, and see whether I can work around in _tkinter. Regards, Martin diff -ur tk8.4.13/generic/tkWindow.c tk8.4.13.modified/generic/tkWindow.c --- tk8.4.13/generic/tkWindow.c 2006-04-04 23:49:57.000000000 +0200 +++ tk8.4.13.modified/generic/tkWindow.c 2006-04-30 21:41:37.000000000 +0200 @@ -3108,6 +3108,7 @@ Tcl_DStringFree(&class); if (code != TCL_OK) { + Tcl_MutexUnlock(&windowMutex); goto done; } Tcl_ResetResult(interp); @@ -3124,6 +3125,7 @@ Tcl_SetVar(interp, "geometry", geometry, TCL_GLOBAL_ONLY); code = Tcl_VarEval(interp, "wm geometry . ", geometry, (char *) NULL); if (code != TCL_OK) { + Tcl_MutexUnlock(&windowMutex); goto done; } geometry = NULL;

Thomas Wouters wrote:
I have now reported the underlying Tk bug at http://sourceforge.net/tracker/index.php?func=detail&aid=1479587&group_id=12997&atid=112997 and worked around it in _tkinter.c. Regards, Martin
participants (3)
-
"Martin v. Löwis"
-
Jeff Epler
-
Thomas Wouters