BIND 10 #1828: Python tests print warnings about unclosed file handles / sockets

BIND 10 Development do-not-reply at isc.org
Thu Jun 14 07:59:02 UTC 2012


#1828: Python tests print warnings about unclosed file handles / sockets
-------------------------------------+-------------------------------------
                   Reporter:  muks   |                 Owner:  jinmei
                       Type:         |                Status:  reviewing
  defect                             |             Milestone:
                   Priority:         |  Sprint-20120619
  medium                             |            Resolution:
                  Component:         |             Sensitive:  0
  Unclassified                       |           Sub-Project:  DNS
                   Keywords:         |  Estimated Difficulty:  4
            Defect Severity:  N/A    |           Total Hours:  0
Feature Depending on Ticket:         |
        Add Hours to Ticket:  0      |
                  Internal?:  0      |
-------------------------------------+-------------------------------------
Changes (by muks):

 * owner:  muks => jinmei


Comment:

 Replying to [comment:20 jinmei]:
 > '''general'''
 >
 > - is it possible to make the test fail if this warning is triggered?
 >   since the need for it isn't obvious, it's pretty easy to introduce
 >   new ones without automatic and demanding check.
 > - related to the previous point, I didn't check if this branch fixes
 >   all current warnings.

 It is possible to assert if a warning is generated by using
 `warnings.catch_warnings()', but as you note, not all warnings are fixed
 by this branch as the reason for some are not obvious.

 > '''bindctl_test.py'''
 >
 > Maybe it's a matter of taste, but I guess this may be better:
 >
 > {{{#!cpp
 >         with open(os.devnull, 'w') as f:
 >             sys.stdout = f
 >             cmd = bindcmd.BindCmdInterpreter()
 >           ...
 >             os.remove(csvfilename)
 > }}}
 >
 > In the original trac1828 version it's not so obvious to me that why we
 > do `sys.stdout.close()`.  And the `with` version is more exception
 > safe.
 >
 > Also, while it'd probably beyond the scope of this task, it'd be
 > better to restore sys.stdout in tearDown(); otherwise if this test
 > fails sys.stdout will be kept faked in subsequent tests.

 Done :)

 > '''ddns_test'''
 >
 > - I suspect the intent of this close may not be obvious and suggest
 >   adding some comments about why we do it:
 > {{{#!python
 >         if self.ddns_server._listen_socket is not None:
 >             self.ddns_server._listen_socket.close()
 > }}}

 Comment has been added.

 > - `TestDDNSServer.test_listen`: it rather seems to be the task of
 >   `DDNSServer`.  Since it's the one who opens the socket on
 >   construction, I think it should explicitly close it at least in
 >   shutdown_cleanup().  Then this test would call this method on
 >   `ddnss`, rather than trying to close it by itself.

 Done.

 > '''msgq_test'''
 >
 > - I think this one should be fixed within msgq: setup_listener()
 >   should close the socket in the `except` block.

 Done.

 > - I'd simplify infinite_sender() as follows:
 > {{{#!python
 >         with socket.socketpair(socket.AF_UNIX, socket.SOCK_STREAM)[1] as
 write:
 >             msgq.register_socket(write)
 >             # Keep sending while it is not closed by the msgq
 >             try:
 >                 while True:
 >                     sender(msgq, write)
 >             except socket.error:
 >                 pass
 > }}}

 This `with` statement leaves pair[0] open and generates a warning.

 > - infinite_sender/send_many: like others, the intent of the close()
 >   isn't obvious to me.  But in these cases I cannot come up with a
 >   cleaner alternative.  If this is the least bad one, I'd at least
 >   clarify the intent in comments.

 Same condition as above, I've not used `with` for these. The `.close()`
 itself should not need explanation, no? We are closing when done with the
 object.

 > '''xfrout_test'''
 > - test_guess_remote: `with` should be able to be used in these cases.

 Uses `with` now.

 > - test_sock_file_in_use: same comment as bindctl_test.py applies.
 >   besides, I don't even understand why we need to tweak stdout here.
 >   I guess it was for very older versions that dumped noisy logs
 >   directly to stdout.  I don't see any noise or other failures even if
 >   I remove this trick.  I suggest we simply stop tweaking.

 Done.

 > - test_remove_unused_sock_file_dir: likewise.

 Done.

 >
 > '''xfrout.py'''
 >
 > - `_guess_remote`: I'd prefer using `with`
 > {{{#!python
 >         if socket.has_ipv6:
 >             with socket.fromfd(sock_fd, socket.AF_INET6,
 socket.SOCK_STREAM) \
 >                     as s:
 >                 peer = s.getpeername()
 >         else:
 >             # To make it work even on hosts without IPv6 support
 >             # (Any idea how to simulate this in test?)
 >             with socket.fromfd(sock_fd, socket.AF_INET,
 socket.SOCK_STREAM) \
 >                     as s:
 >                 peer = s.getpeername()
 > }}}
 >   although admittedly this version doesn't seem to look very simple.
 >   In any case, 'close()' can be done much earlier than the current
 >   position.

 I've made it look like this now:

 {{{
         if socket.has_ipv6:
             socktype = socket.AF_INET6
         else:
             # To make it work even on hosts without IPv6 support
             # (Any idea how to simulate this in test?)
             socktype = socket.AF_INET

         with socket.fromfd(sock_fd, socktype, socket.SOCK_STREAM) as sock:
             peer = sock.getpeername()
 }}}

 > - `_sock_file_in_use`: I'd use `with` here (and it would make much
 >   simpler)

 Done.

 > '''zonemgr_test'''
 >
 > - I don't see the need for tweaking stderr here in the first place.
 >   Also, zonemgr itself has this problem for the socketpair.  What we
 >   should do is to close them appropriately.

 Done.

 > '''sockcreator_test'''
 >
 > - at least this can be revised with `with`:
 > {{{#!python
 >         p1 = socket.fromfd(t2.read_fd(), socket.AF_UNIX,
 socket.SOCK_STREAM)
 > }}}

 Done.

 >
 > '''socketsession_test'''
 >
 > - shouldn't it better to close self.start_listen in tearDown() (and
 >   maybe in start_listen() if it can be called multiple times)?

 This has been fixed now.

 > - check_push_and_pop: at least sock should be able to be managed with
 `with`.

 Done.

 > - test_bad_pop: can use `with`:
 > {{{#!python
 >         with self.accept_forwarder() as accept_sock:
 >             receiver = SocketSessionReceiver(accept_sock)
 >             s.close()
 >             self.assertRaises(SocketSessionError, receiver.pop)
 > }}}

 Done.

-- 
Ticket URL: <http://bind10.isc.org/ticket/1828#comment:22>
BIND 10 Development <http://bind10.isc.org>
BIND 10 Development


More information about the bind10-tickets mailing list