Skip to content

Commit

Permalink
Merge pull request tornadoweb#996 from cardoe/exception-fix
Browse files Browse the repository at this point in the history
use errno attr instead of index into args for errno
  • Loading branch information
bdarnell committed Mar 3, 2014
2 parents d4627e0 + f81a25e commit b1f5cc5
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 17 deletions.
7 changes: 3 additions & 4 deletions tornado/ioloop.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
from tornado.log import app_log, gen_log
from tornado import stack_context
from tornado.util import Configurable
from tornado.util import errno_from_exception

try:
import signal
Expand Down Expand Up @@ -724,9 +725,7 @@ def start(self):
# two ways EINTR might be signaled:
# * e.errno == errno.EINTR
# * e.args is like (errno.EINTR, 'Interrupted system call')
if (getattr(e, 'errno', None) == errno.EINTR or
(isinstance(getattr(e, 'args', None), tuple) and
len(e.args) == 2 and e.args[0] == errno.EINTR)):
if errno_from_exception(e) == errno.EINTR:
continue
else:
raise
Expand All @@ -746,7 +745,7 @@ def start(self):
fd_obj, handler_func = self._handlers[fd]
handler_func(fd_obj, events)
except (OSError, IOError) as e:
if e.args[0] == errno.EPIPE:
if errno_from_exception(e) == errno.EPIPE:
# Happens when the client closes the connection
pass
else:
Expand Down
10 changes: 5 additions & 5 deletions tornado/iostream.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
from tornado.log import gen_log, app_log
from tornado.netutil import ssl_wrap_socket, ssl_match_hostname, SSLCertificateError
from tornado import stack_context
from tornado.util import bytes_type
from tornado.util import bytes_type, errno_from_exception

try:
from tornado.platform.posix import _set_nonblocking
Expand Down Expand Up @@ -766,8 +766,8 @@ def connect(self, address, callback=None, server_hostname=None):
# returned immediately when attempting to connect to
# localhost, so handle them the same way as an error
# reported later in _handle_connect.
if (e.args[0] != errno.EINPROGRESS and
e.args[0] not in _ERRNO_WOULDBLOCK):
if (errno_from_exception(e) != errno.EINPROGRESS and
errno_from_exception(e) not in _ERRNO_WOULDBLOCK):
gen_log.warning("Connect error on fd %s: %s",
self.socket.fileno(), e)
self.close(exc_info=True)
Expand Down Expand Up @@ -1026,9 +1026,9 @@ def read_from_fd(self):
try:
chunk = os.read(self.fd, self.read_chunk_size)
except (IOError, OSError) as e:
if e.args[0] in _ERRNO_WOULDBLOCK:
if errno_from_exception(e) in _ERRNO_WOULDBLOCK:
return None
elif e.args[0] == errno.EBADF:
elif errno_from_exception(e) == errno.EBADF:
# If the writing half of a pipe is closed, select will
# report it as readable but reads will fail with EBADF.
self.close(exc_info=True)
Expand Down
10 changes: 5 additions & 5 deletions tornado/netutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
from tornado.concurrent import dummy_executor, run_on_executor
from tornado.ioloop import IOLoop
from tornado.platform.auto import set_close_exec
from tornado.util import u, Configurable
from tornado.util import u, Configurable, errno_from_exception

if hasattr(ssl, 'match_hostname') and hasattr(ssl, 'CertificateError'): # python 3.2+
ssl_match_hostname = ssl.match_hostname
Expand Down Expand Up @@ -84,7 +84,7 @@ def bind_sockets(port, address=None, family=socket.AF_UNSPEC, backlog=128, flags
try:
sock = socket.socket(af, socktype, proto)
except socket.error as e:
if e.args[0] == errno.EAFNOSUPPORT:
if errno_from_exception(e) == errno.EAFNOSUPPORT:
continue
raise
set_close_exec(sock.fileno())
Expand Down Expand Up @@ -133,7 +133,7 @@ def bind_unix_socket(file, mode=0o600, backlog=128):
try:
st = os.stat(file)
except OSError as err:
if err.errno != errno.ENOENT:
if errno_from_exception(err) != errno.ENOENT:
raise
else:
if stat.S_ISSOCK(st.st_mode):
Expand Down Expand Up @@ -165,12 +165,12 @@ def accept_handler(fd, events):
except socket.error as e:
# EWOULDBLOCK and EAGAIN indicate we have accepted every
# connection that is available.
if e.args[0] in (errno.EWOULDBLOCK, errno.EAGAIN):
if errno_from_exception(e) in (errno.EWOULDBLOCK, errno.EAGAIN):
return
# ECONNABORTED indicates that there was a connection
# but it was closed while still in the accept queue.
# (observed on FreeBSD).
if e.args[0] == errno.ECONNABORTED:
if errno_from_exception(e) == errno.ECONNABORTED:
continue
raise
callback(connection, address)
Expand Down
5 changes: 3 additions & 2 deletions tornado/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
from tornado.log import gen_log
from tornado.platform.auto import set_close_exec
from tornado import stack_context
from tornado.util import errno_from_exception

try:
long # py2
Expand Down Expand Up @@ -136,7 +137,7 @@ def start_child(i):
try:
pid, status = os.wait()
except OSError as e:
if e.errno == errno.EINTR:
if errno_from_exception(e) == errno.EINTR:
continue
raise
if pid not in children:
Expand Down Expand Up @@ -283,7 +284,7 @@ def _try_cleanup_process(cls, pid):
try:
ret_pid, status = os.waitpid(pid, os.WNOHANG)
except OSError as e:
if e.args[0] == errno.ECHILD:
if errno_from_exception(e) == errno.ECHILD:
return
if ret_pid == 0:
return
Expand Down
3 changes: 2 additions & 1 deletion tornado/tcpserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from tornado.iostream import IOStream, SSLIOStream
from tornado.netutil import bind_sockets, add_accept_handler, ssl_wrap_socket
from tornado import process
from tornado.util import errno_from_exception


class TCPServer(object):
Expand Down Expand Up @@ -231,7 +232,7 @@ def _handle_connection(self, connection, address):
# SSLIOStream._do_ssl_handshake).
# To test this behavior, try nmap with the -sT flag.
# https://github.com/facebook/tornado/pull/750
if err.args[0] in (errno.ECONNABORTED, errno.EINVAL):
if errno_from_exception(err) in (errno.ECONNABORTED, errno.EINVAL):
return connection.close()
else:
raise
Expand Down
18 changes: 18 additions & 0 deletions tornado/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,24 @@ def exec_in(code, glob, loc=None):
""")


def errno_from_exception(e):
"""Provides the errno from an Exception object.
There are cases that the errno attribute was not set so we pull
the errno out of the args but if someone instatiates an Exception
without any args you will get a tuple error. So this function
abstracts all that behavior to give you a safe way to get the
errno.
"""

if hasattr(e, 'errno'):
return e.errno
elif e.args:
return e.args[0]
else:
return None


class Configurable(object):
"""Base class for configurable interfaces.
Expand Down

0 comments on commit b1f5cc5

Please sign in to comment.