boost :: io_service,threads和std :: set

时间:2012-01-29 22:52:22

标签: c++ multithreading boost boost-asio

如果有一些事情比调试试图描述bug本身的多线程应用程序更困难。

  • 我有两个boost :: threads(应用程序和显示)。
  • 两者都使用相同的asio :: io_service来完成他们的工作。 显示线程有一个std :: set类型的window *,它是我用来包装winapi窗口管理的类。
  • 我使用自定义消息队列来传达这两个线程。
  • 其中一条消息(终止)用于通知显示线程它不能“发布”任何更多方法,并且必须调用thread_group.remove_thread并自行删除。
  • 线程有一个变量(状态),用于标记线程的状态(运行,暂停,终止)。
  • 如果它正在运行,它“发布”它的update()方法,该方法迭代std :: set并在它包含的每个窗口*中调用update方法。
  • 如果它被终止,它会清除std :: set,将自己从thread_group中删除,并且不再发布任何工作。

问题:一段时间,当试图关闭应用程序时,线程的更新方法在线程被“终止”并且std :: set被清除后运行。然后update方法尝试迭代std :: set并发生SIGSEGV。这只发生在应用程序的每10次运行中1次,我很难猜测出错了什么。

我会尝试发布相关代码,如果需要更多代码,我会尝试添加它。

int main(int argc, char **argv)
{
    boost::asio::io_service ios;
    boost::asio::strand     strand(ios);
    boost::thread_group     threads;
    owl::system::pump       pump;

    application app(&threads, &strand, &pump);
    owl::system::display display(&strand, &pump);

    ios.run();
    threads.join_all();

    return 0;
}
...
void display::on_terminate()
{
    close_all_windows();
}
...
void display::close_all_windows()
{
    windows.move_first();
    while (!windows.eof())
    {
        window* win = windows.value();
        win->destroy();
        delete win;
        windows.move_next();
    }
    windows.clear();
    check_no_window();
}
...
void display::on_update()
{
    if (windows.size())
    {
        windows.move_first();
        while (!windows.eof())
        {
            windows.value()->update();
            windows.move_next(); // Here happens the SIGSEGV
        }
    }
}

类显示继承管理线程执行的类子系统。这是涉及执行on_update()

的相关代码
void subsystem::do_update()
{
    message* msg;

    size_t message_count = messages.size();
    for (size_t i=0; i<message_count; i++)
    {
        msg = messages[i];
        process_message(msg);
        strand->dispatch(strand->wrap(boost::bind(&message::deallocate, msg)));
    }

    switch (state)
    {
        case running:
        {
            on_update();
        }
        break;
        case paused:
        {
            // Do not update. Just check the queue and sleep
            sleep(10);
        }
        break;
        case terminated:
        {
            do_terminate();
            return;
        }
        break;
    }
        strand->post(strand->wrap(boost::bind(&subsystem::check_for_messages, this)));
}

void subsystem::check_for_messages()
{
        messages.clear();
    pump->get_messages(this, messages);
    ios->post(boost::bind(&subsystem::do_update, this));
}

SIGSEGV恰好在尝试递增std :: set迭代器时发生。

Child process PID: 2272
Program received signal SIGSEGV, Segmentation fault.
In std::_Rb_tree_increment(std::_Rb_tree_node_base const*) ()
stl_tree.h:269

0 个答案:

没有答案