Determining the error that closed a socket

265 views
Skip to first unread message

A. Jesse Jiryu Davis

unread,
Mar 24, 2012, 2:38:10 PM3/24/12
to python-...@googlegroups.com
Hi, I'm using IOStream.set_close_callback(), and I'm trying to determine what error exactly caused the socket to be closed, so I can raise an appropriate exception. For example, using regular sockets, I can distinguish between a bad hostname versus a refused connection:

>>> import socket
>>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> sock.settimeout(1)
>>> try: sock.connect(('asdf', 27017))
... except Exception, e: print e
...
[Errno 8] nodename nor servname provided, or not known
>>> try: sock.connect(('localhost', 27017))
... except Exception, e: print e
...
[Errno 61] Connection refused

With IOStream, however, I can't tell the difference between these errors, I only know that the socket was closed:

>>> import socket; from tornado import iostream, ioloop
>>> loop = ioloop.IOLoop.instance()
>>> def closed():
...     loop.stop();  print 'closed'
...
>>> stream = iostream.IOStream(socket.socket(socket.AF_INET, socket.SOCK_STREAM))
>>> stream.set_close_callback(closed)
>>> stream.connect(('asdf', 27017))
>>> loop.start()
closed
>>> stream = iostream.IOStream(socket.socket(socket.AF_INET, socket.SOCK_STREAM))
>>> stream.set_close_callback(closed)
>>> stream.connect(('localhost', 27017))
>>> loop.start()
closed

If I turn on logging I can see that IOStream logs a specific error, but I can't actually make different decisions in my code based on what error occurred. Additionally, I can't do getsockopt(socket.SOL_SOCKET, socket.SO_ERROR) in my closed callback, because the socket's file descriptor is already closed by the time the callback is executed.

Any suggestions for determining the nature of a connection error? If not, would you consider a patch that passes the errno to the closed callback?

Thanks,
Jesse

Ben Darnell

unread,
Mar 24, 2012, 3:03:02 PM3/24/12
to python-...@googlegroups.com
Unfortunately we don't currently expose any information about the
error to the close callback. It would be nice to add this, but it
would have to be done in a backwards-compatible way. Maybe a flag to
set_close_callback to indicate whether the callback can accept an
error code?

-Ben

A. Jesse Jiryu Davis

unread,
Mar 24, 2012, 3:25:36 PM3/24/12
to python-...@googlegroups.com
Yeah, I was thinking something similar. What should the flag be called, "pass_errno"?


On Saturday, March 24, 2012 3:03:02 PM UTC-4, Ben Darnell wrote:
Unfortunately we don't currently expose any information about the
error to the close callback.  It would be nice to add this, but it
would have to be done in a backwards-compatible way.  Maybe a flag to
set_close_callback to indicate whether the callback can accept an
error code?

-Ben

Ben Darnell

unread,
Mar 24, 2012, 4:01:53 PM3/24/12
to python-...@googlegroups.com
There's more that can go wrong than just an errno, so we should
probably pass the Exception object (or maybe the whole exc_info
triple).

If there were other changes to this callback signature in the future,
I don't think we'd want to have a bunch of boolean arguments to
set_close_callback to turn them on and off piecemeal (but then
something like callback_version=2 is also pretty ugly).

Maybe IOStream should just have an error attribute (like
tornado.httpclient.HTTPResponse) that contains the Exception that
caused the connection to be closed (if any). This would make the
cause of the failure accessible to the application without changing
the callback signature.

-Ben

A. Jesse Jiryu Davis

unread,
Mar 24, 2012, 4:30:00 PM3/24/12
to python-...@googlegroups.com
That sounds smart all around.


On Saturday, March 24, 2012 4:01:53 PM UTC-4, Ben Darnell wrote:
There's more that can go wrong than just an errno, so we should
probably pass the Exception object (or maybe the whole exc_info
triple).

If there were other changes to this callback signature in the future,
I don't think we'd want to have a bunch of boolean arguments to
set_close_callback to turn them on and off piecemeal (but then
something like callback_version=2 is also pretty ugly).

Maybe IOStream should just have an error attribute (like
tornado.httpclient.​HTTPResponse) that contains the Exception that
caused the connection to be closed (if any).  This would make the
cause of the failure accessible to the application without changing
the callback signature.

-Ben

A. Jesse Jiryu Davis

unread,
Apr 11, 2012, 8:26:46 PM4/11/12
to python-...@googlegroups.com
Ben, sorry for the delay, how does this look to you?:

https://github.com/ajdavis/tornado/commit/536d0c0a02691b348a421b61f167989f18ef3596

Feedback welcome, this is my first time modifying Tornado.

A. Jesse Jiryu Davis

unread,
Jun 1, 2012, 11:15:46 AM6/1/12
to python-...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages