[
https://issues.apache.org/jira/browse/THRIFT-6107?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Dmytro Shteflyuk updated THRIFT-6107:
-------------------------------------
Description:
h3. Problem
{{Thrift::NonblockingServer}} can read multiple framed requests from one
connection and assign them to separate worker threads. A worker writes its
response as soon as its handler finishes. If a later request completes first,
its reply is written to the shared connection before the earlier reply.
h3. Client impact
Clients that intentionally pipeline requests on one connection can receive
replies in an order different from the request order. The generated Ruby client
maintains pending sequence IDs in send order, so it can reject such a reply as
the wrong method or sequence ID.
Applications that use only the synchronous generated client methods, with one
request in flight per connection, do not encounter this behavior. Sharing one
generated client instance between threads is separately unsupported; that is
not required to reproduce this issue.
h3. Reproduction
Use one connection and send two requests without waiting for the first reply:
{code:ruby}
client.send_block # handler waits
handler.block_started.pop
client.send_greeting(true) # handler completes first
processor_finished.pop
# Before the fix, emitted framed reply sequence IDs are [1, 0].
handler.unblock(1)
client.recv_block # receives the greeting reply first
{code}
h3. Sequence diagram
!nonblocking-reply-order.svg|width=900!
h3. Expected behavior
A connection must publish reply-bearing requests in the order their frames were
accepted, even when their handlers complete out of order. Oneway requests,
handler failures, connection removal, partial writes, and shutdown must not
leave a missing sequence that indefinitely blocks later replies. Requests on
different connections should remain independently concurrent.
was:
h3. Problem
{{Thrift::NonblockingServer}} can read multiple framed requests from one
connection and assign them to separate worker threads. A worker writes its
response as soon as its handler finishes. If a later request completes first,
its reply is written to the shared connection before the earlier reply.
h3. Client impact
Clients that intentionally pipeline requests on one connection can receive
replies in an order different from the request order. The generated Ruby client
maintains pending sequence IDs in send order, so it can reject such a reply as
the wrong method or sequence ID.
Applications that use only the synchronous generated client methods, with one
request in flight per connection, do not encounter this behavior. Sharing one
generated client instance between threads is separately unsupported; that is
not required to reproduce this issue.
h3. Reproduction
Use one connection and send two requests without waiting for the first reply:
{code:ruby}
client.send_block # handler waits
handler.block_started.pop
client.send_greeting(true) # handler completes first
processor_finished.pop
# Before the fix, emitted framed reply sequence IDs are [1, 0].
handler.unblock(1)
client.recv_block # receives the greeting reply first
{code}
h3. Sequence diagram
!nonblocking-reply-order.png|width=900!
h3. Expected behavior
A connection must publish reply-bearing requests in the order their frames were
accepted, even when their handlers complete out of order. Oneway requests,
handler failures, connection removal, partial writes, and shutdown must not
leave a missing sequence that indefinitely blocks later replies. Requests on
different connections should remain independently concurrent.
> Ruby NonblockingServer can send replies out of request order
> ------------------------------------------------------------
>
> Key: THRIFT-6107
> URL: https://issues.apache.org/jira/browse/THRIFT-6107
> Project: Thrift
> Issue Type: Bug
> Components: Ruby - Library
> Reporter: Dmytro Shteflyuk
> Assignee: Dmytro Shteflyuk
> Priority: Major
> Attachments: nonblocking-reply-order.png, nonblocking-reply-order.svg
>
>
> h3. Problem
> {{Thrift::NonblockingServer}} can read multiple framed requests from one
> connection and assign them to separate worker threads. A worker writes its
> response as soon as its handler finishes. If a later request completes first,
> its reply is written to the shared connection before the earlier reply.
> h3. Client impact
> Clients that intentionally pipeline requests on one connection can receive
> replies in an order different from the request order. The generated Ruby
> client maintains pending sequence IDs in send order, so it can reject such a
> reply as the wrong method or sequence ID.
> Applications that use only the synchronous generated client methods, with one
> request in flight per connection, do not encounter this behavior. Sharing one
> generated client instance between threads is separately unsupported; that is
> not required to reproduce this issue.
> h3. Reproduction
> Use one connection and send two requests without waiting for the first reply:
> {code:ruby}
> client.send_block # handler waits
> handler.block_started.pop
> client.send_greeting(true) # handler completes first
> processor_finished.pop
> # Before the fix, emitted framed reply sequence IDs are [1, 0].
> handler.unblock(1)
> client.recv_block # receives the greeting reply first
> {code}
> h3. Sequence diagram
> !nonblocking-reply-order.svg|width=900!
> h3. Expected behavior
> A connection must publish reply-bearing requests in the order their frames
> were accepted, even when their handlers complete out of order. Oneway
> requests, handler failures, connection removal, partial writes, and shutdown
> must not leave a missing sequence that indefinitely blocks later replies.
> Requests on different connections should remain independently concurrent.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)