【问题标题】:Twisted memory leak when connect attempt failed连接尝试失败时扭曲的内存泄漏
【发布时间】:2013-08-10 09:47:26
【问题描述】:

我被扭曲的内存泄漏折磨。

这是我的代码:

# Python:  Python 2.6.6 (r266:84297, Aug 24 2010, 18:46:32) [MSC v.1500 32 bit (Intel)] on win32
# Twisted: Twisted-12.2.0.win32-py2.6
# OS:      Windows 7 (64bit)
from twisted.internet.protocol import Protocol, ClientFactory
from twisted.internet import reactor


class Echo(Protocol):
    def __del__(self):
        print 'Echo.__del__'

    def connectionMade(self):
        print 'Echo.connectionMade'
        self.transport.write('Hello world!')


class EchoClientFactory(ClientFactory):
    def __del__(self):
        print 'EchoClientFactory.__del__'

    def startedConnecting(self, connector):
        print 'Started connecting ...'

    def buildProtocol(self, addr):
        print 'connected. %r' % addr
        return Echo()

    def clientConnectionFailed(self, connector, reason):
        print 'Connection failed.'


def connect(ip, port):
    factory = EchoClientFactory()
    reactor.connectTCP(ip, port, factory)


##Start
import gc
gc.enable()
gc.set_debug(gc.DEBUG_LEAK)

# Trying to connect to a port that does not exist
connect('127.0.0.1', 7777)

reactor.callLater(5, reactor.stop)
reactor.run()

# Show garbages
print "gc.collect()"
gc.collect()
print 'gc.garbage:', len(gc.garbage)

for i, item in enumerate(gc.garbage):
    print '%d) %r' % (i + 1, item)

运行后,gc 显示发生内存泄漏:

运行后,gc 显示发生内存泄漏:

运行后,gc 显示发生内存泄漏:

Started connecting ...
Connection failed.
EchoClientFactory.__del__
gc.collect()
gc: collectable <Client 02CEA7B0>
gc: collectable <dict 02CEFC00>
gc: collectable <tuple 02B13FD0>
gc: collectable <list 02CD2558>
gc: collectable <instancemethod 02818E40>
gc: collectable <instancemethod 02CF04B8>
gc: collectable <tuple 02B205F8>
gc.garbage: 7
1) <<class 'twisted.internet.tcp.Client'> to ('127.0.0.1', 7777) at 2cea7b0>
2) {'_tempDataBuffer': [], 'protocol': None, '_tempDataLen': 0, 'realAddress': ('127.0.0.1', 7777), 'doRead': <bound method Client.doConnect of <<class 'twisted.internet.tcp.Client'> to ('127.0.0.1', 7777) at 2cea7b0>>, 'doWrite': <bound method Client.doConnect of <<class 'twisted.internet.tcp.Client'> to ('127.0.0.1', 7777) at 2cea7b0>>, 'reactor': <twisted.internet.selectreactor.SelectReactor object at 0x02699D50>, 'addr': ('127.0.0.1', 7777)}
3) ('127.0.0.1', 7777)
4) []
5) <bound method Client.doConnect of <<class 'twisted.internet.tcp.Client'> to ('127.0.0.1', 7777) at 2cea7b0>>
6) <bound method Client.doConnect of <<class 'twisted.internet.tcp.Client'> to ('127.0.0.1', 7777) at 2cea7b0>>
7) ('127.0.0.1', 7777)

仅在连接失败时发生。

有什么想法吗?

【问题讨论】:

  • 从来没有在 python 中为垃圾收集而烦恼,但是内存中有垃圾是很常见的。尤其是当您尝试运行失败的方法时(请注意,您的所有垃圾都与此失败的尝试连接到不存在的端口相关联)。我只是收集垃圾然后继续前进,为什么要担心这个?
  • 感谢您的通知!因为我的程序需要管理数百个设备,连接到它们并从中获取状态,如果断开连接或连接失败,它需要在几秒钟内重新连接。而且这个程序需要永远服务,所以内存泄漏对我来说是个大问题。
  • 对,我明白了。但是你不能只是收集垃圾并接受,当某些对象被删除时(例如,当连接失败时),一些内存不会被“自动”释放?

标签: python memory twisted memory-leaks


【解决方案1】:

__del__ 添加到程序很可能添加 对象泄漏。 __del__ 在循环中的对象上的存在会阻止整个循环被收集。

尝试在不使用__del__ 的任何地方调试您的实际程序。或者,如果您的实际程序使用__del__,请尝试摆脱它。

【讨论】:

    【解决方案2】:

    也许我找到了解决办法。

    在扭曲的源代码中,打开这个文件:Python26\site-packages\twisted\internet\base.py

    class BaseConnector(styles.Ephemeral):
        .
        .
        .
    
        def connectionFailed(self, reason):
            self.cancelTimeout()
            if self.transport.doWrite == self.transport.doConnect:    # 1
                del self.transport.doRead                             # 2
                del self.transport.doWrite                            # 3
            self.transport = None
            self.state = "disconnected"
            self.factory.clientConnectionFailed(self, reason)
            if self.state == "disconnected":
                # factory hasn't called our connect() method
                self.factory.doStop()
                self.factoryStarted = 0
        .
        .
        .
    

    标有 1,2,3 的行是我新添加的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多