【问题标题】:boost tcp socket stuck in write_someboost tcp 套接字卡在 write_some
【发布时间】:2019-09-09 09:51:00
【问题描述】:

我有一个 boost tcp ip 套接字卡在 write_some 函数中 接收器部分卡在死锁中(这是另一个与 tcp 套接字无关的问题)。我成功地模拟了在接收线程中永远休眠的问题。

即使我重新启动发件人,它也会挂在同一行

有没有办法设置超时,以防卡在这种状态以重新启动连接?如果我使用 async_write_some 会是一个解决方案吗?

当我在发送方执行 gstack 时,我可以看到它卡在从 /lib64/libc.so.6 调用 poll() 的 write_some 函数中。在以下行中

socket->write_some(boost::asio::buffer(pData ,nLength, error);

接收者网络统计

发件人 netstat,我看到了一些 netstat 输出为 fin_wait1 的情况,在某些情况下它已建立(但代码仍然卡在 write_some 中)

初始化发送方套接字

socket = boost::make_shared<boost::asio::ip::tcp::socket>(boost::asio::ip::tcp::socket(io_service,boost::asio::ip::tcp::endpoint, 
boost::asio::ip::tcp::v4(),portNumber)))
    // Set a deadline for the asynchronous operation.
boost::asio::deadline_timer pConnectTimer = ...;
pConnectTimer->expires_from_now(boost::posix_time::seconds(10));
boost::asio::socket_base::keep_alive option(true);
socket->set_option(option);
// Start the asynchronous connect itself.
socket->async_connect(endpoint,boost::bind(&CrXdrQueuetoSocket::ConnectCallback, this, std::ref(pi_xdrTarget),
        socket,boost::asio::placeholders::error));

//Poll io service only one time
io_service .poll_one(); 

【问题讨论】:

  • 这里有问题。 FIN_WAIT_1 表示您已关闭套接字(发送了 FIN)并正在等待对等方确认 FIN。因此,您不能同时在send() 中被屏蔽。
  • 肯定有比眼前所见更多的东西。为我们提供一个最小的可重现示例,以便我们可以看到发送方套接字发生了什么。此外,您可能想查看tcpdumpwireshark 或您拥有的实际数据包流。

标签: tcp boost-asio


【解决方案1】:

使用我的水晶球:你是否在传递fds(例如供第三方或遗留代码使用)?

您可能会遇到一个典型的陷阱。

在套接字代码中,需要有一 (1) 个套接字所有者来关闭它。在并发代码中,确保在该时间点之后没有其他人拥有 fd 的副本非常重要,因为这会为竞争条件打开它。

例如,同一个 fd 在关闭后将被重新使用,然后另一个线程可能会认为它仍然是旧连接而使用该 fd。

这个错误看起来不太可能,但人们很容易犯,因为他们觉得“它很安全,fd 已关闭,所以无论如何后面的所有操作都会失败”。

我已经在代码中发现了一些错误,在这些错误中,应用程序偶尔会意外地对数据库服务器进行模糊测试,因为它们会将任意数据发送到重新打开到 mysql 的连接。

请注意,您可以使用shutdown() 代替close(),这会使所有挂起的操作取消并且新操作失败,而无需释放 fd 以供重用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-10
    • 2012-12-28
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多