boost::asio::strand 在 Ubuntu 11.04 (boost_all_dev 1.42) 上是不是损坏

Posted

技术标签:

【中文标题】boost::asio::strand 在 Ubuntu 11.04 (boost_all_dev 1.42) 上是不是损坏【英文标题】:Is boost::asio::strand broken on Ubuntu 11.04 (boost_all_dev 1.42)boost::asio::strand 在 Ubuntu 11.04 (boost_all_dev 1.42) 上是否损坏 【发布时间】:2011-05-18 18:17:35 【问题描述】:

我有一个使用 io_service 和多个线程的程序。

它实例化了一些套接字对象。这些对象每个都有一个同步链。所有对 async_read()、async_write() 和类似函数的调用都通过 strand_.wrap(boost::bind(...))。每个对象还有一个 int interlock_ 变量,初始化为 0。

在这些函数之一(on-data-receive 回调)中,我执行以下操作:

Class::startRead(...)

...
    boost::asio::async_read(socket_, boost::asio::buffer(ptr, 16384), boost::asio::transfer_at_least(1),
        strand_.wrap(boost::bind(&EagerConnection::on_read, this, placeholders::error, placeholders::bytes_transferred)));


Class::on_read(...)

...
    startRead();
    assert(0 == __sync_fetch_and_add(&interlock_, 1));
    onData_();
    assert(1 == __sync_fetch_and_add(&interlock_, -1));

因为一切都是通过链同步的,所以第一个断言永远不应该触发。不过,确实火了!当我在 GDB 中查看值时,interlock_ 的最终值为 2,这意味着对 on_read() 的两个单独调用同时处于活动状态。

这是否意味着 boost::asio::strand 坏了? (我已经检查过我在完成函数中没有任何重入——onData_ 信号处理程序不会重新调用 on_data())。

“早期”的 startRead 会以某种方式导致立即重新进入吗? (async_x 和 strand 的语义似乎都表明它不能)

如果您真的非常想查看课程的完整内容,可以将其作为要点:https://gist.github.com/979212

【问题讨论】:

【参考方案1】:

我发现了一些小问题(?):

Minor:切换interlock_strand_的初始化顺序。通过声明 interlock_ _after_ strand_ 成员来修复它;

readIn 函数不返回任何值(未初始化的数据)。您可能打算返回n


好消息:

使用 valgrind 运行结果清晰。 使用 helgrind 运行很明显(但是:我猜我在最小示例中没有使用线程;不知道 boost::asioboost::signals 内部结构)。

【讨论】:

【参考方案2】:

我正在尝试重现事物,但执行此操作时我的安装未能引发断言。

我在要点末尾添加了以下片段:

int split(std::string const &src, char ch, std::string &oLeft, std::string &oRight)

    std::size_t pos = src.find(ch);
    if (pos == std::string::npos)
    
        oLeft = src;
        oRight.clear();
        return 1;
     else
    
        oLeft = src.substr(0, pos);
        oRight = src.substr(pos+1);
        return 2;
    


namespace 

    boost::asio::io_service svc;
    EagerConnection c(svc);

    void onconnect()
    
        std::cout << "ONCONNECT" << std::endl;
        const char data[] = "GET / HTTP/1.0\r\n\r\n"; 
        c.writeOut(data, sizeof(data));
    

    void ondata()
    
        std::cout << "ONDATA" << std::endl;
        std::ostringstream oss;
        char buf[1024];
        int read;
        while ((read = c.readIn(buf, 1024)))
            oss.write(buf, read);
        std::cout << "response: " << oss.str() << std::endl;
    

    void ondisconnect()
    
        std::cout << "ON__DIS__CONNECT" << std::endl;
    



int main(int argc, char* argv[])

    if (argc>1 && argv[1])
    
        c.onConnect_.connect(&onconnect);
        c.onData_.connect(&ondata);
        c.onDisconnect_.connect(&ondisconnect);


        c.open(argv[1]);
        svc.run();
    

    return 0;

如您所见,我真的在尝试做 SimplestThingThatCouldPossiblyWork。我的连接/重新连接运行良好(包括增加的退避时间)。

我用这个编译

strand: strand.cpp
    g++ -Wall -Werror -o $@ $^ -g -O0 -lboost_system -lboost_thread -lboost_signals -lpthread

然后调用它

./strand 127.0.0.1:6767

我有一个响应脚本坐在那里(基本上)

netcat -l -p 6767 -e rev

另一件需要注意的事情:写缓冲区似乎从未真正被发送/刷新直到我打断了strand 测试器(客户端)。不管我做多大的data,都会发生这种情况...这可能是由于我缺少一个步骤?

编辑

上测试相同 ubuntu meerkat,gcc 4.4.5,boost 1.42.0 debian sid,gcc 4.5.2-8,boost 1.46.1

【讨论】:

感谢您的尝试!可能是我正在使用的安装(10.04 LTS)有一些在更高版本中修复的错误。不过请注意,我几乎坚持使用那个版本。

以上是关于boost::asio::strand 在 Ubuntu 11.04 (boost_all_dev 1.42) 上是不是损坏的主要内容,如果未能解决你的问题,请参考以下文章

同一主机下两个容器间进行通信(二)2021.07

Ubuntu 下安装 MySQL Workbench

[转]10 Awesome Indicator Applets for Ubuntu’s Unity Desktop

Ubuntu 快速下载

在Ubuntu中安装CodeCheckerNodeNVM:过程与排雷

在Ubuntu中安装CodeCheckerNodeNVM:过程与排雷