2121
2222#include < gtest/gtest.h>
2323#include < atomic>
24+ #include < errno.h>
2425#include " brpc/server.h"
2526
2627#include " brpc/controller.h"
2728#include " brpc/channel.h"
2829#include " brpc/callback.h"
2930#include " brpc/socket.h"
31+ #include " brpc/details/controller_private_accessor.h"
3032#include " brpc/stream_impl.h"
3133#include " brpc/policy/streaming_rpc_protocol.h"
3234#include " echo.pb.h"
@@ -38,12 +40,12 @@ class AfterAcceptStream {
3840
3941class MyServiceWithStream : public test ::EchoService {
4042public:
41- MyServiceWithStream (const brpc::StreamOptions& options)
43+ MyServiceWithStream (const brpc::StreamOptions& options)
4244 : _options(options)
4345 , _after_accept_stream(NULL )
4446 {}
4547 MyServiceWithStream (const brpc::StreamOptions& options,
46- AfterAcceptStream* after_accept_stream)
48+ AfterAcceptStream* after_accept_stream)
4749 : _options(options)
4850 , _after_accept_stream(after_accept_stream)
4951 {}
@@ -53,9 +55,9 @@ class MyServiceWithStream : public test::EchoService {
5355 {}
5456
5557 void Echo (::google::protobuf::RpcController* controller,
56- const ::test::EchoRequest* request,
57- ::test::EchoResponse* response,
58- ::google::protobuf::Closure* done) {
58+ const ::test::EchoRequest* request,
59+ ::test::EchoResponse* response,
60+ ::google::protobuf::Closure* done) {
5961 brpc::ClosureGuard done_guard (done);
6062 response->set_message (request->message ());
6163 brpc::Controller* cntl = (brpc::Controller*)controller;
@@ -125,7 +127,8 @@ class BatchStreamClientHandler : public brpc::StreamInputHandler {
125127
126128 void on_closed (brpc::StreamId /* id*/ ) override {}
127129
128- void on_failed (brpc::StreamId /* id*/ , int /* error_code*/ , const std::string& /* error_text*/ ) override {}
130+ void on_failed (brpc::StreamId /* id*/ , int /* error_code*/ ,
131+ const std::string& /* error_text*/ ) override {}
129132
130133private:
131134 BatchStreamFeedbackRaceState* _state;
@@ -162,7 +165,8 @@ static void* SendTwoMessagesOnServerExtraStream(void* arg) {
162165 std::string payload (64 , ' a' );
163166 butil::IOBuf out;
164167 out.append (payload);
165- state->server_first_write_rc .store (brpc::StreamWrite (sid, out), std::memory_order_relaxed);
168+ state->server_first_write_rc .store (brpc::StreamWrite (sid, out),
169+ std::memory_order_relaxed);
166170 }
167171
168172 // 2) Then send another byte. This write should become writable only after
@@ -226,12 +230,59 @@ static void SetAtomicTrue(std::atomic<bool>* f) {
226230
227231static bool WaitForTrue (const std::atomic<bool >& f, int timeout_ms) {
228232 const int64_t deadline_us = butil::gettimeofday_us () + (int64_t )timeout_ms * 1000L ;
229- while (!f.load (std::memory_order_acquire) && butil::gettimeofday_us () < deadline_us) {
233+ while (!f.load (std::memory_order_acquire) &&
234+ butil::gettimeofday_us () < deadline_us) {
230235 usleep (1000 );
231236 }
232237 return f.load (std::memory_order_acquire);
233238}
234239
240+ class MyServiceWithStreamAndFailedSocket : public test ::EchoService {
241+ public:
242+ explicit MyServiceWithStreamAndFailedSocket (const brpc::StreamOptions& options)
243+ : _options(options) {}
244+
245+ void Echo (::google::protobuf::RpcController* controller,
246+ const ::test::EchoRequest* request,
247+ ::test::EchoResponse* response,
248+ ::google::protobuf::Closure* done) override {
249+ brpc::ClosureGuard done_guard (done);
250+ response->set_message (request->message ());
251+ brpc::Controller* cntl = static_cast <brpc::Controller*>(controller);
252+ brpc::StreamId response_stream;
253+ ASSERT_EQ (0 , StreamAccept (&response_stream, *cntl, &_options));
254+ brpc::ControllerPrivateAccessor accessor (cntl);
255+ ASSERT_TRUE (accessor.get_sending_socket () != NULL );
256+ accessor.get_sending_socket ()->SetFailed ();
257+ }
258+
259+ private:
260+ brpc::StreamOptions _options;
261+ };
262+
263+ TEST_F (StreamingRpcTest, set_host_socket_returns_error_when_socket_is_failed) {
264+ brpc::SocketOptions socket_options;
265+ brpc::SocketId host_socket_id;
266+ ASSERT_EQ (0 , brpc::Socket::Create (socket_options, &host_socket_id));
267+ brpc::SocketUniquePtr host_socket;
268+ ASSERT_EQ (0 , brpc::Socket::Address (host_socket_id, &host_socket));
269+ ASSERT_EQ (0 , host_socket->SetFailed ());
270+
271+ brpc::StreamId stream_id;
272+ brpc::StreamOptions stream_options;
273+ ASSERT_EQ (0 , brpc::Stream::Create (stream_options, NULL , &stream_id, false ));
274+ brpc::ScopedStream stream_guard (stream_id);
275+
276+ brpc::SocketUniquePtr stream_socket;
277+ ASSERT_EQ (0 , brpc::Socket::Address (stream_id, &stream_socket));
278+ brpc::Stream* stream = static_cast <brpc::Stream*>(stream_socket->conn ());
279+
280+ errno = 0 ;
281+ ASSERT_EQ (-1 , stream->SetHostSocket (host_socket.get ()));
282+ ASSERT_NE (0 , errno);
283+ ASSERT_TRUE (stream->_host_socket == NULL );
284+ }
285+
235286TEST_F (StreamingRpcTest, sanity) {
236287 brpc::Server server;
237288 MyServiceWithStream service;
@@ -393,6 +444,39 @@ class OrderedInputHandler : public brpc::StreamInputHandler {
393444 HandlerControl* _cntl;
394445};
395446
447+ TEST_F (StreamingRpcTest, server_failed_socket_before_response_closes_stream_without_abort) {
448+ OrderedInputHandler handler;
449+ brpc::StreamOptions response_stream_options;
450+ response_stream_options.handler = &handler;
451+ brpc::Server server;
452+ MyServiceWithStreamAndFailedSocket service (response_stream_options);
453+ ASSERT_EQ (0 , server.AddService (&service, brpc::SERVER_DOESNT_OWN_SERVICE));
454+ ASSERT_EQ (0 , server.Start (9007 , NULL ));
455+
456+ brpc::Channel channel;
457+ ASSERT_EQ (0 , channel.Init (" 127.0.0.1:9007" , NULL ));
458+ brpc::Controller cntl;
459+ brpc::StreamId request_stream;
460+ ASSERT_EQ (0 , StreamCreate (&request_stream, cntl, NULL ));
461+ brpc::ScopedStream stream_guard (request_stream);
462+
463+ test::EchoService_Stub stub (&channel);
464+ stub.Echo (&cntl, &request, &response, NULL );
465+ ASSERT_TRUE (cntl.Failed ());
466+
467+ for (int i = 0 ; i < 10000 && !handler.stopped (); ++i) {
468+ usleep (100 );
469+ }
470+
471+ server.Stop (0 );
472+ server.Join ();
473+
474+ ASSERT_TRUE (handler.stopped ());
475+ ASSERT_TRUE (handler.failed ());
476+ ASSERT_EQ (0 , handler.idle_times ());
477+ ASSERT_EQ (0 , handler._expected_next_value );
478+ }
479+
396480TEST_F (StreamingRpcTest, received_in_order) {
397481 OrderedInputHandler handler;
398482 brpc::StreamOptions opt;
0 commit comments