Release the memory of threading.Timer in Python

人走茶凉 提交于 2019-12-25 02:51:47

问题


I'm doing a packet injection with scapy and creating a threading.Timer which deletes the packet information from the dictionary after 10 seconds. If I receive a response before 10 seconds, I'm cancelling the Timer and deleting the packet information from the dictionary. Since I'm cancelling the Timer, I can put .join() here. But when the Timer expires, there's no mechanism to .join().

When I run the program, the memory keeps on increasing. No doubt, increasing is slow (Initially 2% in a 1 GB RAM system. In 20 minutes, it went to 3.9%). But still it keeps on increasing. I tried gc.collect(). But it's of no help. I'm monitoring the memory with top.

Below is the code. Sorry for the large code. I guess it's better to give the whole code to know if somewhere I'm missing something.

from threading import Timer
from scapy.all import *
import gc

class ProcessPacket():
    #To write the packets to the response.pcap file    
    def pcapWrite(self, pkts):
        writerResponse(pkts)
        writerResponse.flush()
        return

    #cancels the Timer upon receiving a response
    def timerCancel(self, ipPort):
        if self.pktInfo[ipPort]["timer"].isAlive():
            self.pktInfo[ipPort]["timer"].cancel()
            self.pktInfo[ipPort]["timer"].join()  
        self.delete(ipPort)
        return

    #deletes the packet information from pktInfo
    def delete(self, ipPort):
        if self.pktInfo.has_key(ipPort):
            self.pcapWrite(self.pktInfo[ipPort]["packets"])
            del self.pktInfo[ipPort]
        return

    #processes the received packet and sends the response
    def createSend(self, pkt, ipPort):
        self.pktInfo[ipPort]["packets"] = [pkt]
        self.pktInfo[ipPort]["timer"] = Timer(10, self.delete, args=[ipPort])        
        myPkt = IP(src = pkt[IP].dst, dst = pkt[IP].src)/ TCP(dport = pkt[TCP].sport, sport = pkt[TCP].dport, flags = 'SA')
        self.pktInfo[ipPort]["packets"].append(myPkt)        
        send(myPkt, verbose=0)
        self.pktInfo[ipPort]["timer"].start()
        return

    #constructor
    def __init__(self):
        self.count = 0
        self.writerResponse=PcapWriter('response.pcap',append = True)
        self.pktInfo = {}
        return

    #from sniff
    def pktCallback(self,pkt):    
        ipPort = pkt[IP].src + str(pkt[TCP].sport) + pkt[IP].dst + str(pkt[TCP].dport)
        flag=pkt.sprintf('%TCP.flags%')
        if self.count == 10:
            self.count = 0
            gc.collect()
        if not self.pktInfo.has_key(ipPort) and flag == 'S':
            self.pktInfo[ipPort] = {}
            self.createSend(pkt, ipPort)
            self.count += 1
        elif self.pktInfo.has_key(ipPort):
            self.timerCancel(ipPort)
            self.count += 1
        return

#custom filter for sniff
def myFilter(pkt):
    if pkt.haslayer(IP):
        if pkt[IP].src == "172.16.0.1":
            return 1
        return 0                

if __name__ == '__main__':      
    respondObj = ProcessPacket()
    sniff(iface = 'eth0', filter = "tcp", prn = respondObj.pktCallback, lfilter = myFilter)

In the program, I don't see any other memory consuming factor other than pktInfo and the Timer. pktInfo is increasing and decreasing so the problem is with Timer. How can I free memory of the expired or cancelled Timers?

EDIT 1: I modified the delete() function:

#deletes the packet information from pktInfo
def delete(self, ipPort):
    if self.pktInfo.has_key(ipPort):
        print "Before", len(self.pktinfo.keys()), sys.getsizeof(self.pktinfo)
        self.pcapWrite(self.pktInfo[ipPort]["packets"])
        self.pktInfo[ipPort]["timer"]=None
        self.pktInfo[ipPort]=None
        del self.pktInfo[ipPort]
        gc.collect()
        print "After", len(self.pktinfo.keys()), sys.getsizeof(self.pktinfo)
    return

After deletion the number of elements in self.pktinfo decreases. The size of the self.pktinfo remains same for a long time but eventually changes (decreases or increases). But the memory of system doesn't seem to be released. top shows the same behaviour that the memory used by the program is continuously increasing.


回答1:


Release all references to unneeded Timer objects. (e.g. self.pktInfo[ipPort]["timer"] = None) - if you don't the garbage collector won't free up anything.



来源:https://stackoverflow.com/questions/29918905/release-the-memory-of-threading-timer-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!