Ticket #6216: resolvconf-close-6216.2.patch

File resolvconf-close-6216.2.patch, 2.7 KB (added by Jordan Hagan, 9 years ago)

Revised patch addressing concerns raised in first review

  • twisted/topfiles/6216.bugfix

     
     1Fixed problem where twisted.names.client.Resolver was not closing open file handles which can lead to an out of file descriptor error on PyPy.
     2 No newline at end of file
  • twisted/names/client.py

     
    130130        self.maybeParseConfig()
    131131
    132132
     133    def _openFile(self, path):
     134        """
     135        Wrapper used for opening files in the class, exists primarily for unit
     136        testing purposes.
     137        """
     138        return FilePath(path).open()
     139
     140
    133141    def maybeParseConfig(self):
    134142        if self.resolv is None:
    135143            # Don't try to parse it, don't set up a call loop
    136144            return
    137145
    138146        try:
    139             resolvConf = FilePath(self.resolv).open()
     147            resolvConf = self._openFile(self.resolv)
    140148        except IOError as e:
    141149            if e.errno == errno.ENOENT:
    142150                # Missing resolv.conf is treated the same as an empty resolv.conf
     
    149157                log.msg('%s changed, reparsing' % (self.resolv,))
    150158                self._lastResolvTime = mtime
    151159                self.parseConfig(resolvConf)
     160            resolvConf.close()
    152161
    153162        # Check again in a little while
    154163        self._parseCall = self._reactor.callLater(
  • twisted/names/test/test_client.py

     
    1111
    1212from twisted.python.compat import set
    1313from twisted.python import failure
     14from twisted.python.filepath import FilePath
    1415from twisted.python.runtime import platform
    1516
    1617from twisted.internet import defer
     
    287288        self.assertEqual([("127.0.0.1", 53)], resolver.dynServers)
    288289
    289290
     291    def test_closesResolvConf(self):
     292        """
     293        Ensures that L{client.Resolver} closes the resolvConf file when done.
     294        """
     295        handle = FilePath(self.mktemp())
     296        resolvConf = handle.open(mode='w+')
     297        self.addCleanup(handle.remove)
     298
     299        _openFile = lambda self, path: resolvConf
     300        self.patch(client.Resolver, '_openFile', _openFile)
     301        client.Resolver(servers=["example.com", 53], resolv='/etc/resolv.conf',
     302            reactor=Clock())
     303
     304        self.assertTrue(resolvConf.closed)
     305
     306
    290307    def test_domainEmptyArgument(self):
    291308        """
    292309        L{client.Resolver.parseConfig} treats a I{domain} line without an