How to combat "Fatal IO error 11 (Resource temporarily unavailable) on X server" in multithreaded gtkmm application?

v010dya picture v010dya · Jul 12, 2015 · Viewed 9.8k times · Source

I am attempting to write a gtkmm application that uses C++11 multithreading. However, i keep running into Fatal IO error 11 (Resource temporarily unavailable) on X server error.

I have several Gtk::Image objects on my window. Each one is in its own Gtk::EventBox and periodically i have to change the image. To do that i have created a class that holds the event box for the specific block, and it has a function that removes the previous image, generates the new one and places it there.

Here's a block of code:

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();

When error 11 occurs some of the numbers do not get printed to std::cerr, but where the problem happens is different each time (i have recently observed it crashing after 12 and after 123). Thus i come to the conclusion that the resource that is being used somewhere is not the image, but the eventBox. But after initialisation of the program it is not accessed anywhere outside of this function, and this function is wrapped with the std::atomic_flag lock.

Questions: What can be a reason for such behaviour? Can i ensure that it doesn't happen? Or can i catch this error and expect to recover from it?

Edits:

I have attempted

  1. I tried to change from using std::thread to Glib::Threads::Thread, but to no avail, still getting the same error.
  2. Having read this i have attempted to add GDK_SYNCHRONIZE to environment, this has generated [xcb] Unknown request in queue while dequeuing/[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called error. This lead me to this post, after which i have attempted to call XInitThreads() before starting the new thread (both via Glib::Threads::Thread and std::thread), but this did nothing positive; except that once by some fluke the thread has actually executed the entire function (displayed '4' on screen), but then still managed to die with the same error 11 message.

Answer

Phillip picture Phillip · Jul 15, 2015

GTK is not thread safe. You can use a global lock to access GTK from threads, but the best practice is to only invoke GTK functions from the main thread. You can use Glib::signal_idle().connect and Glib::MainContext::invoke() for that.