如何在X服务器上打击"致命IO错误11(资源暂时不可用)"在多线程gtkmm应用程序?

时间:2015-07-12 10:52:15

标签: multithreading c++11 gtkmm

我正在尝试编写一个使用C ++ 11多线程的gtkmm应用程序。但是,我一直遇到Fatal IO error 11 (Resource temporarily unavailable) on X server错误。

我的窗口上有几个Gtk::Image个对象。每个人都有自己的Gtk::EventBox,我必须定期更改图片。为此,我创建了一个包含特定块的事件框的类,它有一个删除前一个图像的函数,生成新图像并将其放在那里。

这是一段代码:

while (lock_flag.test_and_set()) {} // std::atomic_flag lock
// ...
std::cerr << 1;
eventBox->foreach(
    [eb = this->eventBox](Gtk::Widget& w)
    {
        eb->Gtk::Container::remove(w);
    }
);
std::cerr << 2;
eventBox->add(*im);
std::cerr << 3;
eventBox->show_all_children();
std::cerr << 4;
// ...
lock_flag.clear();

error 11出现时,某些数字不会打印到std::cerr,但问题发生的地方每次都不同(我最近观察到它在12之后和123之后崩溃)。因此,我得出的结论是,在某处使用的资源不是图像,而是eventBox。但是在程序初始化之后,它不会在此函数之外的任何地方访问,并且此函数包含std::atomic_flag锁。

问题:这种行为可能是什么原因?我可以确保它不会发生吗?或者我能抓住这个错误并期望从中恢复吗?

编辑:

我试过了

  1. 我尝试使用std::thread更改为Glib::Threads::Thread,但无济于事,仍然遇到同样的错误。
  2. 阅读this后我尝试将GDK_SYNCHRONIZE添加到环境中,这会产生[xcb] Unknown request in queue while dequeuing/[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called错误。这导致我this post,之后我尝试在开始新主题之前调用XInitThreads()(通过Glib::Threads::Threadstd::thread),但这没有任何积极意义;除了曾经有一些侥幸,线程实际上已经执行了整个功能(在屏幕上显示&#39; 4&#39;)但是仍然设法使用相同的error 11消息而死亡。

1 个答案:

答案 0 :(得分:2)

最后,我是如何解决所有问题的。

通过Phillip提供的链接,我发现了Glib::signal_timeout(),这使我能够在我的代码中完全重新考虑并行性的概念。

以下是我必须要做的事情:

if(running) return;
running = true;

static bool firstTime = true;
if(firstTime)
{
    XInitThreads();
    firstTime=false;
}

std::function<void()> f = [this] () -> void
{
    while(running)
    {
        this->takeStep();
        std::this_thread::sleep_for(std::chrono::milliseconds(300));
    }
};

std::thread(f).detach();

这可以很容易地重写为:

if(running) return;
running = true;

runningHandle = Glib::signal_timeout().connect( sigc::mem_fun(*this, &ArtificialIntelligence::takeStep), 300 );

然后我只需要将runningHandle.disconnect();添加到我的暂停功能中,并且一切都开始非常好。事实上,GUI响应的速度已经提高。

因此,如果其他人试图“采取行动,然后睡觉”过程,这是一个更好的选择。当然,应用程序中没有设置周期性,然后应该寻求其他解决方案。