【问题标题】:C++/Thrift: Is TThreadedServer::stop() thread-safe?C++/Thrift:TThreadedServer::stop() 线程安全吗?
【发布时间】:2019-05-23 21:04:39
【问题描述】:

我想在单独的线程中使用TTheadedServer 来控制何时停止/启动它。我的应用程序只需要 1 个控制线程和 1 个处理线程。我不希望有多个客户,因为我使用 Thrift 作为中继。 TSimpleServer 不是线程安全的,所以我放弃了这个选项。

我做了一个小例子来检查它是否是线程安全的,并使用 clang 的 thread-sanitizer 来确保它是线程安全的。这是示例

std::shared_ptr<MyHandler> handler = std::make_shared<MyHandler>();

int port = 9090;

th::stdcxx::shared_ptr<th::TProcessor>         processor(new HandlerProcessor(handler));
th::stdcxx::shared_ptr<tht::TServerTransport>  serverTransport(new tht::TServerSocket(port));
th::stdcxx::shared_ptr<tht::TTransportFactory> transportFactory(
    new tht::TBufferedTransportFactory());
th::stdcxx::shared_ptr<thp::TProtocolFactory> protocolFactory(new thp::TBinaryProtocolFactory());

ths::TThreadedServer server(processor, serverTransport, transportFactory, protocolFactory);

// start in another thread
std::thread          t(&ths::TThreadedServer::serve, &server);
t.detach();

std::this_thread::sleep_for(std::chrono::seconds(5));

// stop in this thread
server.stop();

std::this_thread::sleep_for(std::chrono::seconds(5));

所以我要做的就是在另一个线程中用serve() 启动服务器,然后等待一段时间,然后停止它。我用线程清理器运行了这个,并收到了一些线程安全警告。我在这里提到2:

第一:thrift/lib/cpp/src/thrift/transport/TServerSocket.cpp:244,在:

interruptableChildren_ = enable;

第二:thrift/lib/cpp/src/thrift/transport/TServerSocket.cpp:654,在:

if (-1 == send(notifySocket, cast_sockopt(&byte), sizeof(int8_t), 0)) {
  GlobalOutput.perror("TServerSocket::notify() send() ", THRIFT_GET_SOCKET_ERROR);
}

那么我做的对吗? TThreadedServer 控制器线程安全吗? Thread-sanitizer 似乎不这么认为,尽管测试程序可以正常运行。

我正在使用 Thrift 0.12.0。

【问题讨论】:

    标签: c++ multithreading c++11 rpc thrift


    【解决方案1】:

    它是线程安全的,但它可能存在在实践中永远不会出现的多线程错误。例如,在interruptableChildren_ 的情况下 - 流程是您可以在主线程中配置它的值,但随后它被接受器线程读取(TServerSocket::acceptImpl 运行的地方)。从理论上讲,您可以从不受保护的变量中进行读写。在实践中,您永远不会在启动服务器后更改它 std::thread t(&ths::TThreadedServer::serve, &server); 行,因此不会发生数据竞争。

    我猜notify() 的情况类似。

    【讨论】:

    • 感谢您的回答。你能在提到这一点的地方提供一些参考吗?我找不到。
    • 我已经很久没有阅读他们的文档了。 4 年前,我使用 thrift 编写了 prod quality RPC 服务,所以我根据我的个人经验知道。虽然我使用了更旧的版本(当然有更多的错误:))。但是,这里是关于 thrift 中各种线程模型的简短回答:stackoverflow.com/a/28547917/2280111
    • 我知道那个帖子。然而,它并没有回答我提出的问题。没有文档说明这一点,这很奇怪。
    • 我不是这个包的维护者,但我可以尝试解释它的逻辑。您没有指定 TThreadedServer 是线程安全的,因为它就像指定船舶防水 :) 该组件的全部目标是打开多个线程并管理它们。 “线程”甚至在它的名字中。因此,只要您根据他们的预期流程使用它,他们就计划它是线程安全的。它可能有错误,并且在使用奇怪的用法时可能是非线程安全的,例如从错误的线程或错误的阶段调用成员函数。
    • 感谢您尝试解释它。虽然我同意你的结论,但假设可能不正确。有可能认为这在阻塞意义上是有用的,用户应该阻塞他们的主线程,如果他们对此不满意,他们可能只使用TNonBlockingServer。这是一个巨大的问题,这些都没有记录在案,因为它为猜测打开了大门。
    猜你喜欢
    • 1970-01-01
    • 2019-09-20
    • 2021-01-15
    • 2010-11-24
    • 2011-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多