Issue2471
Created on 2016-02-22.23:04:32 by nickmbailey, last changed 2016-03-14.16:40:48 by zyasoft.
msg10762 (view) |
Author: Nick (nickmbailey) |
Date: 2016-02-22.23:04:31 |
|
I think Jython is using netty's channel future incorrectly and causing a deadlock.
The netty docs say it is preferred to add asynchronous listeners rather than calling sync()/await() directly.
https://github.com/netty/netty/blob/4.0/transport/src/main/java/io/netty/channel/ChannelFuture.java#L96
Jython is doing things the incorrect way when closing sockets:
https://github.com/jythontools/jython/blob/master/Lib/_socket.py#L1059
In my twisted application running on jython I can easily cause deadlocks by using apache bench to load test the twisted web server. I think we can safely just add the rest of the shutdown code as a listener on the channel future like so:
diff --git a/Lib/_socket.py b/Lib/_socket.py
index 3b658e5..56d8f4d 100644
--- a/Lib/_socket.py
+++ b/Lib/_socket.py
@@ -1055,11 +1055,10 @@ class _realsocket(object):
if self.channel is None:
return
- try:
- self.channel.close().sync()
- except RejectedExecutionException:
- # Do not care about tasks that attempt to schedule after close
- pass
+ closeFuture = self.channel.close()
+ closeFuture.addListener(self.finishClosing)
+
+ def finishClosing(self, _):
if self.socket_type == SERVER_SOCKET:
log.debug("Shutting down server socket parent group", extra={"sock": self})
self.parent_group.shutdownGracefully(0, 100, TimeUnit.MILLISECONDS)
If I apply that patch, I can no longer cause the deadlock.
|
msg10763 (view) |
Author: Jim Baker (zyasoft) |
Date: 2016-02-22.23:59:07 |
|
Looks reasonable, although we should apply a test on the future (isSuccess()) before adding the listener.
|
msg10764 (view) |
Author: Nick (nickmbailey) |
Date: 2016-02-23.16:31:23 |
|
Well the promise itself will call the listener immediately if the promise is already done. Is there another reason to check success beforehand?
|
msg10771 (view) |
Author: Jim Baker (zyasoft) |
Date: 2016-02-24.06:26:41 |
|
I was attempting to justify my response to why use isSuccess() when closing this bug out when I realized:
I am wrong, the noise is test_socket is OK, compared to the alternative.
If we don't attempt to add the listener *always*, we simply have a silent race where the thread pool resource may not be cleaned up. And that's far worse.
See https://github.com/netty/netty/issues/2166 - perhaps we can tune the logging.
So latest fix is in https://hg.python.org/jython/rev/08b7720fd321
|
|
Date |
User |
Action |
Args |
2016-03-14 16:40:48 | zyasoft | set | status: pending -> closed |
2016-02-24 06:26:41 | zyasoft | set | status: open -> pending assignee: zyasoft resolution: fixed messages:
+ msg10771 |
2016-02-24 03:11:47 | zyasoft | set | priority: high milestone: Jython 2.7.1 |
2016-02-23 16:31:24 | nickmbailey | set | messages:
+ msg10764 |
2016-02-22 23:59:08 | zyasoft | set | nosy:
+ zyasoft messages:
+ msg10763 |
2016-02-22 23:04:32 | nickmbailey | create | |
|