Michael Czajkowski created THRIFT-4858:
------------------------------------------

             Summary: Java TThreadPoolServer calls TBaseProcesser twice, 
erroneously
                 Key: THRIFT-4858
                 URL: https://issues.apache.org/jira/browse/THRIFT-4858
             Project: Thrift
          Issue Type: Bug
          Components: Java - Library
    Affects Versions: 0.12.0
         Environment: Here is some information on my environment and code that 
calls Thrift.

Environment: Red Hat Linux 7.6, Java 1.8, Thrift 0.12.0. Both my client and 
server are in Java. However, I have also seen this when a Python client calls 
the Java server.

Here is what I do to set up the server, my service Iface name is 
"AlgorithmRepository" ...

{{TServerTransport transport = new TServerSocket(10202);}}
{{ TProcessor processor = new AlgorithmRepository.Processor<>(this);}}
{{ Args args = new 
TThreadPoolServer.Args(transport).processor(processor).inputTransportFactory(new
 TFramedTransport.Factory()).outputTransportFactory(new 
TFramedTransport.Factory()).protocolFactory(new TBinaryProtocol.Factory());}}
{{ final TServer server = new TThreadPoolServer(args);}}
{{ new Thread(server::serve).start();}}

That last line corresponds to the Thread you see at the bottom of the exception.

It is worth noting we did also set the Input and Output Protocol Factories too 
and it had no affect on the result.

We saw on stackoverflow that if you don't have the same Transport type, it will 
fail to function. Here is client code that sets this up:

{{TTransport transport = new TFramedTransport(new TSocket(host, port, 
socketTimeoutMillis));}}

I'd be happy to share more client code if you felt it was something the client 
is doing wrong.

 
            Reporter: Michael Czajkowski


I've spotted an error in using java libthrift that I'd like to call to your 
attention. It is in version 0.12.0, but I see it in other versions. I will 
comment about the other versions at the end, please read - it may be very 
*important* to you.

I create a TThreadPoolServer, and when my client calls a method, the server 
spawns off a worker thread and when it gets to this line:

{{if(stopped_ || !processor.process(inputProtocol, outputProtocol)) {}}

{{break;}}
{{ }}}

It will call a TBaseProcessor's process method, which can only return either 
True or throw an Exception. In my case, it gets to the very bottom and calls 
the ProcessFunction fn properly:

{{fn.process(msg.seqid, in, out, iface);}}

Followed by returning true. However, since the TThreadPoolServer will not 
"break" out of the while(true) loop it is in, it will attempt to call the 
TBaseProcessor's process method again and this time around I get an exception 
when this line is called on TBaseProcessor's process method:

{{TMessage msg = in.readMessageBegin();}}

Exception is:

17844 [pool-6-thread-5] ERROR org.apache.thrift.server.TThreadPoolServer - 
Thrift error occurred during processing of message.

{{org.apache.thrift.transport.TTransportException}}
{{ at 
org.apache.thrift.transport.TIOStreamTransport.read(TIOStreamTransport.java:132)}}
{{ at org.apache.thrift.transport.TTransport.readAll(TTransport.java:86)}}
{{ at 
org.apache.thrift.transport.TFramedTransport.readFrame(TFramedTransport.java:132)}}
{{ at 
org.apache.thrift.transport.TFramedTransport.read(TFramedTransport.java:100)}}
{{ 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:33)}}
{{ at 
org.apache.thrift.server.TThreadPoolServer$WorkerProcess.run(TThreadPoolServer.java:318)}}
{{ 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)}}

I surmise because my TProtocol in has already sent the bytes (I am using a 
TBinaryProtocol) to the process function, there is nothing left to read and 
thus we never make it to the next line:

{{ProcessFunction fn = processMap.get(msg.name);}}

For giggles, I decided to remove the ! from the logic, and sure enough it gets 
by but it appears to perhaps cause other problems when a client calls a method 
with zero parameters (e.g. "ping()").

*Other versions:* So far as I can tell this exact same set up is in java 
libthrift 0.9.0, 0.9.1, and 0.9.3.1. However, my Java code works just fine in 
those. I only discovered this problem when I went to upgrade my code to Thrift 
0.12.0. I honestly can't make sense of why that would be OK in those older 
versions but, I've been blissfully unaware of this problem until the upgrade. I 
used TThreadPoolServer then as I do now. I figured perhaps something else is 
happening in Thrift with my TThreadPoolServer. Finally, I did see the problem 
in 0.12.1 and did not test it, though it appears changed in the master branch - 
we tried it and it still has errors.



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

Reply via email to