Skip to content

Instantly share code, notes, and snippets.

@xavfernandez
Created July 2, 2014 21:58
Show Gist options
  • Save xavfernandez/1ea7dc03d5dc793cd082 to your computer and use it in GitHub Desktop.
Save xavfernandez/1ea7dc03d5dc793cd082 to your computer and use it in GitHub Desktop.
Python 3.3 hanging analysis
#/usr/lib/python3.3/subprocess.py, inside def _communicate_with_poll:
while self._fd2file:
timeout = self._remaining_time(endtime)
if timeout is not None and timeout < 0:
raise TimeoutExpired(self.args, orig_timeout)
try:
ready = poller.poll(timeout)
except select.error as e:
if e.args[0] == errno.EINTR:
continue
raise
self._check_timeout(endtime, orig_timeout)
# XXX Rewrite these to use non-blocking I/O on the
# file objects; they are no longer using C stdio!
for fd, mode in ready:
if mode & select.POLLOUT:
chunk = input_view[self._input_offset :
self._input_offset + _PIPE_BUF]
try:
self._input_offset += os.write(fd, chunk)
except OSError as e:
if e.errno == errno.EPIPE:
close_unregister_and_remove(fd)
else:
raise
else:
if self._input_offset >= len(self._input):
close_unregister_and_remove(fd)
elif mode & select_POLLIN_POLLPRI:
data = os.read(fd, 32768)
if not data:
close_unregister_and_remove(fd)
self._fd2output[fd].append(data)
else:
# Ignore hang up or errors.
close_unregister_and_remove(fd)
return (stdout, stderr)
###################################################
Entry for both scenario:
self.stdout.fileno() => 6
self.stderr.fileno() => 8
self._fd2file => {8: <_io.BufferedReader name=8>, 6: <_io.BufferedReader name=6>}
Normal scenario:
ready = poller.poll(timeout) => [(8, 16), (6, 17)]
close_unregister_and_remove(fd) with fd = 8
select_POLLIN_POLLPRI for fd = 6
data = b'Downloading/unpacking INITools\n ...'
self._fd2file => {6: <_io.BufferedReader name=6>}
ready = poller.poll(timeout) => [(6, 16)]
close_unregister_and_remove(fd) with fd = 6
=> DONE and test pass
Stuck scenario:
self.stdout.fileno() => 6
self.stderr.fileno() => 8
self._fd2file => {8: <_io.BufferedReader name=8>, 6: <_io.BufferedReader name=6>}
ready = poller.poll(timeout) => [(6, 1)]
select_POLLIN_POLLPRI for fd = 6
data => b'Downloading/unpacking INITools\n ...'
self._fd2file => {8: <_io.BufferedReader name=8>, 6: <_io.BufferedReader name=6>}
ready = poller.poll(timeout) => STUCK FOREVER
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment