【问题标题】:Running unit tests seems to block io_service indefinitely运行单元测试似乎会无限期地阻止 io_service
【发布时间】:2016-11-04 08:43:22
【问题描述】:

我有一个类使用 asio::generic::stream_protocol::socket 连接到域 (asio::local::stream_protocol::endpoint) 和 TCP 套接字 (asio::ip::tcp::endpoint)。

为了测试该类,我使用Catch 框架在单个文件中进行了一系列单元测试。

我突然遇到一个问题:运行测试时会卡住。将-DASIO_ENABLE_HANDLER_TRACKING 传递给编译器标志我可以看到它卡在async_connect 上。如果我评论除一个之外的所有测试,无论如何都不会发生这种情况。如果我有两个测试,无论它们是连接到域或 tcp 套接字,还是其中一个,我都会遇到阻塞。

Asio 的输出发生了变化,但这是一个示例:

$ tests/unit_tests
@asio|1478248907.301230|0*1|deadline_timer@0x7f96f1c07ad8.async_wait
@asio|1478248907.301276|0*2|resolver@0x7f96f1c07ac0.async_resolve
@asio|1478248907.301322|>1|ec=system:0
@asio|1478248907.301328|<1|
@asio|1478248907.302052|>2|ec=system:0,...
@asio|1478248907.302186|2*3|socket@0x7f96f1c07a20.async_connect
@asio|1478248907.302302|<2|
@asio|1478248907.302468|>3|ec=system:0
@asio|1478248907.302481|<3|
@asio|1478248907.302551|0*4|socket@0x7f96f1c07a20.async_send
@asio|1478248907.302611|>4|ec=system:0,bytes_transferred=23
@asio|1478248907.302617|<4|
@asio|1478248907.302621|0*5|socket@0x7f96f1c07a20.async_receive(null_buffers)
@asio|1478248907.356478|>5|ec=system:0,bytes_transferred=0
@asio|1478248907.356547|<5|
@asio|1478248907.356622|0|socket@0x7f96f1c07a20.close
@asio|1478248907.372967|0|deadline_timer@0x7f96f1c07ad8.cancel
@asio|1478248907.372981|0|resolver@0x7f96f1c07ac0.cancel
@asio|1478248907.373509|0*6|deadline_timer@0x7f96f1d00468.async_wait
@asio|1478248907.373526|0*7|resolver@0x7f96f1d00450.async_resolve
@asio|1478248907.374910|>7|ec=system:0,...
@asio|1478248907.374946|7*8|socket@0x7f96f1d003b0.async_connect
@asio|1478248907.375014|<7|
@asio|1478248907.375127|>8|ec=system:0
@asio|1478248907.375135|<8|

我的问题是:运行打开和关闭连接的单元测试有什么问题?如果这是一个禁忌,你如何编写使用 async_open 的单元测试?

【问题讨论】:

  • 你能提供一个minimal reproducible example吗?处理程序跟踪输出显示两个 async_connect 操作成功完成。如果附加了一个调试器,那么阻塞线程的回溯是什么? async_open 是用户定义的高层操作吗?

标签: c++ sockets c++11 tcp boost-asio


【解决方案1】:

io_servicerunrun_onepollpoll_one 方法,它们实际上执行完成处理程序。 Boost asio 可能有自己的线程,但这些线程的状态可能不正确,无法调用您的处理程序。因此,即使在单元测试中,您也必须弄清楚哪个线程将调用完成处理程序。

其次,run 运行完成,然后返回。根据您的描述(第一次测试成功,第二次失败)听起来您确实调用了run,但没有调用reset 和re-runio_service

【讨论】:

  • 测试没有失败,它只是冻结了。同一个类的不同实例可以共享线程吗? Asio 的所有用途是否共享一个状态?
  • @ruipacheco:您的对象是否可以共享线程,我们无法确定。 Boost asio 在io_service 中有它的状态,你再次决定是共享一个对象还是使用多个实例。 io_service.run() 可以从多个线程中调用。
【解决方案2】:

问题似乎与我迭代 tcp::resolver 输出的方式有关。

【讨论】:

    猜你喜欢
    • 2021-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多