How to deal with "Fatal IO error 11 (resource temporarily unavailable) on the X-server" in a multi-threaded gtkmm application?

I am trying to write a gtkmm application that uses C ++ 11 multithreading. However, I continue to work with the Fatal IO error 11 (Resource temporarily unavailable) on X server .

I have several Gtk::Image objects in my window. Each of them is in its own Gtk::EventBox and periodically changes the image. To do this, I created a class that contains an event field for a specific block, and it has a function that deletes the previous image, generates a new one and puts it there.

Here's the code block:

 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 numbers are not printed on std::cerr , but where the problem occurs, it differs each time (I recently noticed that it crashes after 12 and after 123). Thus, I came to the conclusion that the resource that is used somewhere is not an image, but an eventBox . But after the initialization of the program, it is not available anywhere outside this function, and this function ends with the lock std::atomic_flag .

Questions: What could be causing this behavior? Can I guarantee that this will not happen? Or can I catch this error and expect recovery from it?

Changes:

I tried

  • I tried changing the use of std::thread to Glib::Threads::Thread , but to no avail, still getting the same error.
  • After reading this , I tried to add GDK_SYNCHRONIZE on Wednesday, it caused the error [xcb] Unknown request in queue while dequeuing/[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called . This led me to this post , after which I tried to call XInitThreads() before starting a new thread (both via Glib::Threads::Thread and std::thread ), but it didn’t put anything; except that once some random thread actually performed the entire function ("4" is displayed on the screen), but then it was still possible to die with the same error 11 message.
+5
source share
2 answers

In the end, this is how I solved all the problems.

Following the link provided by Phillip , I found out about Glib::signal_timeout() , and this allowed me to completely rethink the concept of parallelism in my code.

Here is what I had to start with:

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

and this can easily be rewritten as:

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

Then I needed to add runningHandle.disconnect(); into my pause function, and everything began to work wonderfully. In fact, the response speed of the GUI has increased.

So, if someone else is trying to make the process "worked and then sleep," this is a much better alternative. Of course, there are applications in which there is no specified periodicity, and then you need to look for some other solution.

+2
source

GTK is not thread safe. You can use global locking to access GTK from streams , but it is best to use GTK functions only from the main stream. You can use Glib :: signal_idle (). Connect and Glib :: MainContext :: invoke () for what.

+6
source

All Articles