问题
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