Issue1121

classification
Title: listening socket shutdown expects the wrong kind of socket
Type: Severity: normal
Components: Versions: 2.2.2
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: amak Nosy List: amak, glyph
Priority: normal Keywords: twisted

Created on 2008-09-06.16:30:33 by glyph, last changed 2009-01-29.18:39:18 by amak.

Messages
msg3474 (view) Author: Glyph Lefkowitz (glyph) Date: 2008-09-06.16:30:33
From CPython:

>>> s.listen(5)
>>> s.shutdown(socket.SHUT_RDWR)
>>> 

From Jython:

>>> s.listen(5) 
>>> s.shutdown(socket.SHUT_RDWR)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in shutdown
  File "/home/glyph/Projects/Jython/trunk/jython/dist/Lib/socket.py",
line 812, in shutdown
    self.sock_impl.shutdownInput()
  File "/home/glyph/Projects/Jython/trunk/jython/dist/Lib/socket.py",
line 242, in shutdownInput
    self.jsocket.shutdownInput()
AttributeError: sun.nio.ch.ServerSocketAdaptor instance has no attribute
'shutdownInput'
msg3500 (view) Author: Alan Kennedy (amak) Date: 2008-09-13.11:58:37
Although this is not obvious when one is using the C/python socket API,
server sockets do not have read and write channels. 

Server sockets can only accept incoming connections; it is those
'accept'ed connections that have read and write channels that can be
'shutdown'. The java.net.ServerSocket API makes this explicitly clear;
there are no I/O operations on such objects.

http://java.sun.com/j2se/1.5.0/docs/api/java/net/ServerSocket.html

But the sockets returned from the accept call do

http://java.sun.com/j2se/1.5.0/docs/api/java/net/Socket.html

So strictly speaking, this is not a bug; it is an invalid operation.

Nonetheless, the jython socket module should be fixed so that either 

1. A more meaningful error is raised, or
2. The call simply passes silently.

I will be checking in a fix today.
msg3521 (view) Author: Alan Kennedy (amak) Date: 2008-09-13.18:41:13
Fix checked into trunk and release 2.2.

Jython sockets should now have identical behaviour to cpython sockets,
in this circumstance.

Strictly speaking, shutting down I/O on a server socket has no meaning,
because it is merely a connection receiving endpoint, and not a
bi-directional messaging channel, as are connected sockets.

So it should, strictly speaking, raise an exception; this would be the
standard java behaviour.

But the correct thing to do here is to do the same as cpython, i.e. let
the operation succeed.

So jython sockets will now permit shutdown of server sockets, i.e.
sockets that have 'listen'ed; the operation will silently pass, and have
no effect on the socket.
msg4090 (view) Author: Alan Kennedy (amak) Date: 2009-01-27.18:32:55
On re-reading this bug report, I see that fix checked in earlier is
incorrect.

The title of the bug report is very precise: "listening socket shutdown
expects the wrong kind of socket".

That is correct because the existing jython shutdown method for TCP
sockets indeed expects a connected socket, with input and output channels.

But shutdown is also a valid operation on listening sockets.

From what I can see in the java documentation, there is no "shutdown"
method for java ServerSockets or ServerSocketChannels, only a "close"
method. But, the close method is appropriate for a "shutdown" operation,
because it closes the listening socket and cancels all pending
connections in the queue, which is what "shutdown" should do.

http://java.sun.com/j2se/1.5.0/docs/api/java/net/ServerSocket.html#close()

According to my reading, the difference between shutdown and close on
listening sockets is only relevant when multiple processes have the same
socket file descriptor open. For example, this document

http://docs.hp.com/en/J2793-90048/ch03s05.html

says

"""
The shutdown() and close() calls differ in that shutdown() takes effect
regardless of the number of open socket descriptors, while close() takes
effect only when the last process with an open socket descriptor makes
the call. 
"""

But java servers are always multi-threaded, and multiple-process
concerns do not apply.

I will apply a fix in a few days which maps the "shutdown" call on
listening sockets to the underlying ServerSocketChannel.

All opinions are welcome.
msg4107 (view) Author: Alan Kennedy (amak) Date: 2009-01-29.18:39:18
OK, fix checked into release 2.2 at r6000 and trunk at r6001.

Differences between cpython and jython for the shutdown method are
documented on the jython socket module documentation page

http://wiki.python.org/jython/NewSocketModule#Socketshutdown

I have explained the rationale for the implementation choice in this
blog post.

http://jython.xhaus.com/?p=65
Socket shutdown versus socket close on cpython, jython and java.
History
Date User Action Args
2009-01-29 18:39:18amaksetstatus: open -> closed
resolution: accepted -> fixed
messages: + msg4107
2009-01-27 18:32:57amaksetstatus: closed -> open
resolution: fixed -> accepted
messages: + msg4090
2008-09-13 18:41:13amaksetstatus: open -> closed
resolution: fixed
messages: + msg3521
2008-09-13 11:58:41amaksetpriority: normal
assignee: amak
messages: + msg3500
nosy: + amak
versions: + 2.2.2
2008-09-06 20:02:18nrileysetkeywords: + twisted
2008-09-06 16:30:33glyphcreate