pexpect/pexpect — pull request #108 by jquast (2014-08-28 06:22:09+00:00)
Title: Closes issue #103: file descriptor leak on EOF.

Forcefully close the child pty descriptor when EOF is reached.

Without doing so, we have to wait until python's garbage collector
decides to call our __del__ method, which is not deterministic. So,
in such a retry loop as explained in issue #103, it is very possible
to reach "too many open files" on a subsequent fork() call.

This was done using TDD -- we first artificially lower our soft limit
of RLIMIT_NOFILE to be +10 than what we detect to be our limit by
quickly opening a temporary file and evaluating its current file
descriptor number.

Then, we loop N * 2 times of calling /bin/cat, expecting or catching
EOF in various forms to ensure we do not ever reach such "too many
open files" condition. Without the call to 'self.close()' in the EOF
handler, such condition is always reached at exactly the 10th loop.

Another condition must be handled in the expect_loop(), that, when
expecting [many, things, including, or not, EOF], EOF has previously
been caught, but one of the [many, things] are currently matching,
to ensure that those [many, things] are first returned. But once those
patterns have been exausted, check if self.after is set to EOF and to
re-raise the exception to allow the handler to also re-raise
it naturally. This is tested by
``test_donot_reach_max_ptys_expect_includes_EOF()``