[Python-bugs-list] [ python-Bugs-704180 ] Memory leak: threading.Thread.__init__(self, target=self.xx)

SourceForge.net noreply@sourceforge.net
Sun, 16 Mar 2003 08:45:28 -0800


Bugs item #704180, was opened at 2003-03-15 16:44
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=704180&group_id=5470

Category: Threads
Group: Python 2.2.2
Status: Open
Resolution: None
Priority: 5
Submitted By: Darrell Gallion (dgallion)
Assigned to: Nobody/Anonymous (nobody)
Summary: Memory leak: threading.Thread.__init__(self, target=self.xx)

Initial Comment:
This call  
	threading.Thread.__init__(self, target=self.xxx) 
makes this assignment  
	self.__target = target 
Which looks like a circular refrence to me.  
weakref anyone ? 
 
The following test code shows the leak in action. 
 
--Darrell 
 
 
import threading, time 
 
class T1(threading.Thread): 
    def __init__(self, leak=0): 
        self.leak=leak 
        if leak: 
            threading.Thread.__init__(self, target=self.m1) 
        else: 
            threading.Thread.__init__(self) 
        self.start() 
         
    def run(self): 
        pass 
         
    def m1(self): 
        pass 
         
    def __del__(self): 
        print 'DEL:', self, "leak:",self.leak 
         
 
for x in range(10): 
    T1(leak=1) 
for x in range(10): 
    T1() 
time.sleep(1) 
 
 

----------------------------------------------------------------------

>Comment By: Darrell Gallion (dgallion)
Date: 2003-03-16 16:45

Message:
Logged In: YES 
user_id=68151

I know about the __del__ issue with gc, and your right this example worked 
fine with it removed. The much larger app that sent me on this chase wasn't 
fixed by the __del__ method. Yet it was fixed by moving the target method 
to a function call instead of a method on the object. 
 
It's a large app and the timing of when an object is destroyed matters. 
The following helps me see my problem.  
 
import threading, time, weakref 
 
class T1(threading.Thread): 
    def __init__(self): 
        self.go=1 
        threading.Thread.__init__(self, target=self.m1) 
        self.start() 
         
    def m1(self): 
        while self.go: 
            time.sleep(0.0001) 
         
 
objs={} 
while 1: 
    t1 = weakref.ref(T1()) 
    objs[t1]=1 
    t1().go=0 
    time.sleep(0.01) 
    for o in objs.keys(): 
        if o() == None: 
            del objs[o] 
    print len(objs), 
 
 
         
 
 
 

----------------------------------------------------------------------

Comment By: Tim Peters (tim_one)
Date: 2003-03-16 04:39

Message:
Logged In: YES 
user_id=31435

The "leak" is due to that you gave this class a __del__ 
method:  cyclic garbage collection won't magically reclaim 
objects in cycles with __del__ methods.  Remove the 
__del__ and you can run this all day without the process 
size growing.  If you leave the __del__ in, you can find all 
your uncollectible thread objects in gc.garbage (and use 
that to break the cycles and get them collected, if you like --
 I'd recommend not using __del__ at all, though).

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=704180&group_id=5470