Я делаю инъекцию пакета с scapy
и создаю threading.Timer
, который удаляет информацию о пакете из словаря через 10 секунд. Если я получаю ответ до 10 секунд, я отменяю Timer
и удаляю информацию о пакете из словаря. Поскольку я отменяю Таймер, я могу поставить .join()
здесь. Но когда Таймер истекает, нет никакого механизма для .join()
.Освободите память threading.Timer в Python
Когда я запускаю программу, память продолжает расти. Без сомнения, увеличение происходит медленно (сначала 2% в 1 ГБ оперативной памяти, через 20 минут - 3,9%). Но все же он продолжает расти. Я пробовал gc.collect()
. Но это не поможет. Я отслеживаю память с помощью top
.
Ниже приведен код. Извините за большой код. Думаю, лучше дать всему кодексу знать, где-то я чего-то не хватает.
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)
В программе, я не вижу никакой другой памяти потребляя фактор, кроме pktInfo
и Timer
. pktInfo
увеличивается и уменьшается, поэтому проблема заключается в Timer
. Как я могу освободить память просроченных или отмененных таймеров?
РЕДАКТИРОВАТЬ 1: Я изменил delete()
функцию:
#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
После удаления количество элементов в self.pktinfo
уменьшается. Размер self.pktinfo
остается таким же в течение длительного времени, но в конечном итоге изменяется (уменьшается или увеличивается). Но память системы, похоже, не выпущена. top
показывает то же поведение, что память, используемая программой, постоянно увеличивается.
Пробовал. Кажется, не действует. См. Раздел «Редактировать» вопроса. – RatDon
любые отличия в режиме работы с более длинным временем работы, например, через 30 мин/после 1 часа? – knitti
Я запускаю код около 8-9 часов. Невозможно найти разницу. Или разница незначительна. Возможно ли, чтобы 'top' отображал неверное значение или существует ли какая-либо кеш-память, не выпущенная в ОС? – RatDon