[
https://issues.apache.org/jira/browse/THRIFT-4598?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16532852#comment-16532852
]
James E. King III edited comment on THRIFT-4598 at 7/4/18 3:04 PM:
-------------------------------------------------------------------
I did a bunch of work on the C++ library to make it interruptable and thus
stoppable (see THRIFT-2441). On the java side it should be good enough to
close the server socket from a different thread (whichever one is calling
stop()), and that should interrupt the socket read on the server thread. So
make sure the clean exit code path is either calling TServer::stop() *or*
calling TServerSocket::close().
If you look at the TServer.java code, it says:
{noformat}
/**
* Stop the server. This is optional on a per-implementation basis. Not
* all servers are required to be cleanly stoppable.
*/
public void stop() {}
{noformat}
In TThreadPoolServer.java, I see:
{noformat}
public void stop() {
stopped_ = true;
serverTransport_.interrupt();
}
{noformat}
In TServerSocker.java, I see:
{noformat}
public void interrupt() {
// The thread-safeness of this is dubious, but Java documentation suggests
// that it is safe to do this from a different thread context
close();
}
{noformat}
So it looks like the intention is there, but there seem to be a lot of comments
suggesting it may or may not work properly. The java server code probably
needs a refactoring pass; those code paths were written by Mark Slee over 10
years ago. I can tell you the C++ work to make sockets interruptable was very
time consuming and quite difficult to get right, requiring socket pairs so
select could be interrupted on a socket dedicated to that task, otherwise we
found that socket file descriptors were being mishandled. I have no idea if
Java has the same issues or not.
was (Author: jking3):
I did a bunch of work on the C++ library to make it interruptable and thus
stoppable (see THRIFT-2441). On the java side it should be good enough to
close the server socket from a different thread (whichever one is calling
stop()), and that should interrupt the socket read on the server thread. So
make sure the clean exit code path is either calling TServer::stop() *or*
calling TServerSocket::close().
If you look at the TServer.java code, it says:
```
/**
* Stop the server. This is optional on a per-implementation basis. Not
* all servers are required to be cleanly stoppable.
*/
public void stop() {}
```
In TThreadPoolServer.java, I see:
```
public void stop() {
stopped_ = true;
serverTransport_.interrupt();
}
```
In TServerSocker.java, I see:
```
public void interrupt() {
// The thread-safeness of this is dubious, but Java documentation suggests
// that it is safe to do this from a different thread context
close();
}
```
So it looks like the intention is there, but there seem to be a lot of comments
suggesting it may or may not work properly. The java server code probably
needs a refactoring pass; those code paths were written by Mark Slee over 10
years ago. I can tell you the C++ work to make sockets interruptable was very
time consuming and quite difficult to get right, requiring socket pairs so
select could be interrupted on a socket dedicated to that task, otherwise we
found that socket file descriptors were being mishandled. I have no idea if
Java has the same issues or not.
> TBinaryProtocol.readMessageBegin() hangs forever in Java
> --------------------------------------------------------
>
> Key: THRIFT-4598
> URL: https://issues.apache.org/jira/browse/THRIFT-4598
> Project: Thrift
> Issue Type: Bug
> Components: Java - Library
> Affects Versions: 0.11.0
> Environment: Ubuntu Linux 16.04 x86_64
> Reporter: Mario Emmenlauer
> Priority: Major
>
> I run some internal tests for the robustness of our thrift Java server. One
> of the robustness tests is to try to connect to the secure server socket with
> an insecure client and vice versa. This may seem a slightly diabolic test but
> it can be a simple user error to forget enabling or disabling encryption. So
> I think thrift should handle this gracefully.
> However it seems that this test leads to an infinitely hanging server thread!
> The thread blocks the jvm (Java 1.8.0_161 x86_64) from ending. I can see in
> jstack that the main method ends and there are almost no threads left, except
> some garbage collectors and finalizers plus
> org.apache.thrift.server.TThreadPoolServer.
> Here is the call stack of the thrift server thread:
> {code:java}
> java.lang.Thread.State: RUNNABLE
> at java.net.SocketInputStream.socketRead0(Native Method)
> at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
> at java.net.SocketInputStream.read(SocketInputStream.java:171)
> at java.net.SocketInputStream.read(SocketInputStream.java:141)
> at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
> at java.io.BufferedInputStream.read1(BufferedInputStream.java:286)
> at java.io.BufferedInputStream.read(BufferedInputStream.java:345)
> - locked <0x000000067b390fd8> (a java.io.BufferedInputStream)
> at
> org.apache.thrift.transport.TIOStreamTransport.read(TIOStreamTransport.java:127)
> at org.apache.thrift.transport.TTransport.readAll(TTransport.java:86)
> at
> org.apache.thrift.protocol.TBinaryProtocol.readAll(TBinaryProtocol.java:425)
> at
> org.apache.thrift.protocol.TBinaryProtocol.readI32(TBinaryProtocol.java:321)
> at
> org.apache.thrift.protocol.TBinaryProtocol.readMessageBegin(TBinaryProtocol.java:225)
> at org.apache.thrift.TBaseProcessor.process(TBaseProcessor.java:27)
> at
> org.apache.thrift.server.TThreadPoolServer$WorkerProcess.run(TThreadPoolServer.java:310)
> at
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
> at
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
> at java.lang.Thread.run(Thread.java:748)
> {code}
> I already reduced the server socket timeout to 30sec and the requestTimeout
> to 10sec. Is there anything else I can do to timeout readMessageBegin()?
--
This message was sent by Atlassian JIRA
(v7.6.3#76005)