Tcl Source Code

View Ticket
Login
Ticket UUID: 2004654
Title: head: package require foo leaks
Type: Bug Version: obsolete: 8.6a1
Submitter: pointsman Created on: 2008-06-28 00:39:15
Subsystem: 39. Package Manager Assigned To: dgp
Priority: 8 Severity:
Status: Closed Last Modified: 2008-06-28 11:23:43
Resolution: Fixed Closed By: dgp
    Closed on: 2008-06-28 04:23:43
Description:
With tcl head of 2008-06-28, the script 

while 1 {
    interp create moo
    moo eval {catch {package require moo}}
    interp delete moo
}

constantly leak memory. The process grows slowly. There's  almost no danger to lock at it with top or any memory usage monitoring tool. Look at it a few seconds, to see it grow.

That's not a problem of the package manager. The package manager just is implemented in such tcl code, that the leak is triggered. Unfortunately, it's not futher tracked down.

Appended is the relevant part of the valgrind output after running the script

package require foo

(which is the core of the leaking script above).

Requiring a package in scope, e.g. 

package require tcltest

does leak too.
User Comments: dgp added on 2008-06-28 11:23:43:
Logged In: YES 
user_id=80530
Originator: NO


fix committed for 8.4.20, 8.5.3,
and 8.6a2

das added on 2008-06-28 09:12:51:
Logged In: YES 
user_id=90580
Originator: NO

just ran into this as well...
dgp's changes to Tcl_FSGetTranslatedPath() for bug 1972879 omit to decrease the ref count of  the result of the recursive call to Tcl_FSGetTranslatedPath(), the patch below fixes the leak for me, the same change is likely needed on core-8-5-branch and core-8-4-branch...

Index: generic/tclPathObj.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclPathObj.c,v
retrieving revision 1.70
diff -u -p -r1.70 tclPathObj.c
--- generic/tclPathObj.c24 Jun 2008 20:02:31 -00001.70
+++ generic/tclPathObj.c28 Jun 2008 02:06:51 -0000
@@ -1602,10 +1602,15 @@ Tcl_FSGetTranslatedPath(
      * translated version of cwdPtr to normPathPtr, we'll get the
      * translated result we need, and can store it for future use.
      */
-    retObj = Tcl_FSJoinToPath(Tcl_FSGetTranslatedPath(interp,
-    srcFsPathPtr->cwdPtr), 1, &(srcFsPathPtr->normPathPtr));
+
+    Tcl_Obj *translatedCwdPtr = Tcl_FSGetTranslatedPath(interp,
+    srcFsPathPtr->cwdPtr);
+
+    retObj = Tcl_FSJoinToPath(translatedCwdPtr, 1,
+    &(srcFsPathPtr->normPathPtr));
     srcFsPathPtr->translatedPathPtr = retObj;
     Tcl_IncrRefCount(retObj);
+    Tcl_DecrRefCount(translatedCwdPtr);
 } else {
     /*
      * It is a pure absolute, normalized path object. This is

msofer added on 2008-06-28 07:56:17:
Logged In: YES 
user_id=148712
Originator: NO

Note also that what is being leaked is created by TclNewFSPathObj(), so it could be related to dgp's recent work in that area?

msofer added on 2008-06-28 07:49:41:
Logged In: YES 
user_id=148712
Originator: NO

More notes, from the chat:

1. pointsman first discovered the leak while running
     package require foo; proc exit args {}
   under valgrind: stack trace attached and at http://paste.tclers.tk/1031. It shows that processing goes through unknown (and hence uplevel)

2. No leak when the slave does [set x 1], or [glob /*]: a priori not related to either interp creation/deletion or FS 

3. no leak when slave does [catch foo]: a priori not related to unknown or uplevel

So: my first suspect is package handling in init.tcl. Last change seems to be aku's 2008-06-25. Assigning to him for first review.

pointsman added on 2008-06-28 07:39:15:

File Added - 282990: valgrind.out

Attachments: