I'm having a problem with my application. When run on a terminal server which is accessed via ThinClients over X2Go I'm getting the following errors:
[xcb] Unknown sequence number while processing reply
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
../../src/xcb_io.c:643: _XReply: Assertion »!xcb_xlib_threads_sequence_lost« failed.
RITICAL **: 14:51:54.188: draw_box: assertion 'height >= -1' failed
The program received an X Window System error.
This probably reflects a bug in the program.
The error was 'RenderBadPicture (invalid Picture parameter)'.
(Details: serial 6881 error_code 143 request_code 139 minor_code 7)
(Note to programmers: normally, X errors are reported asynchronously;
that is, you will receive the error a while after causing it.
To debug your program, run it with the --sync command line
option to change this behavior. You can then get a meaningful
backtrace from your debugger if you break on the gdk_x_error() function.)
I can't really reproduce the crash. It just happens randomly after hours. This error seems to have something to do with threads. I just can't figure out what I'm doing wrong. Should I call this XInitThreads function somewhere? Should I use special linking flags when compiling my programme?
Am I doing anything wrong with my threads? I'm using them in my DAO class which is based on the wxThread example:
Code: Select all
// Member variables of Dao class
DbHelper dbh; // Class that communicates with the database (libpqxx)
std::map<int, MyThread*> mThreads; // Keep tracks of the threads we've spawned
wxEvtHandler *m_pHandler;
// All the functions in the Dao class are like this
void Dao::Foo() {
wxEvtHandler *handler = m_pHandler;
std::future<void> future = std::async(std::launch::async, [this, handler] {
wxThreadEvent event(wxEVT_THREAD, THREAD_DATA_READY);
event.SetInt(ID_FOO);
event.SetPayload<MyModel>(dbh.Bar());
wxQueueEvent(handler, event.Clone());
});
RunThread(GET_GOAS, std::move(future), handler);
}
Dao::MyThread* Dao::RunThread(int taskId, std::future<void> future, wxEvtHandler *handler) {
// MyThread is a detached wxThread
MyThread *thread = new MyThread(this, taskId, std::move(future), handler);
if (thread->Run() != wxTHREAD_NO_ERROR) {
wxLogError(wxString::Format("Can't create thread with taskID %d.", taskId));
delete thread;
return NULL;
}
mThreads.emplace(thread->GetId(), thread);
return thread;
}
wxThread::ExitCode Dao::MyThread::Entry() {
wxLogInfo("Spawning thread with ID %ld and TaskID %d", GetId(), mTaskId);
bool error = false;
wxString msg = "Done";
try {
std::future_status status = mFuture.wait_for(std::chrono::milliseconds(0));
while (!TestDestroy()) {
if (status == std::future_status::ready) break;
wxThreadEvent event(wxEVT_THREAD, THREAD_UPDATE);
event.SetInt(mTaskId);
event.SetExtraLong(GetId());
// m_pHandler should be OK here.
if (m_pHandler) {
wxQueueEvent(m_pHandler, event.Clone());
}
status = mFuture.wait_for(std::chrono::milliseconds(100));
}
if (status == std::future_status::ready) mFuture.get();
} catch (...) { // Catch the exceptions that my be raised in the future (such as pqxx::exception)
wxLogError(wxString::Format("TaskID=%d - %s", mTaskId, e.what()));
msg = "Error";
}
wxThreadEvent event(wxEVT_THREAD, THREAD_TERMINATED);
event.SetString(msg);
event.SetInt(mTaskId);
event.SetExtraLong(GetId());
if (error) {
event.SetId(THREAD_ERROR);
}
// signal the event handler that this thread is going to be destroyed
if (m_pHandler) {
wxQueueEvent(m_pHandler, event.Clone());
}
return (wxThread::ExitCode)0; // success
}
Code: Select all
/**
* Get a reference to the dao object.
* Sets the DAO's event handler so the thread events are queued in the right handler.
* @param who the calling event handler
* @return a reference to the DAO
*/
Dao& MyApp::GetDao(wxEvtHandler *who) {
mDao.SetHandler(who);
return mDao;
}
// In a class deriving from e.g. wxPanel:
wxGetApp().GetDao(this).Foo();
void MyPanel::OnThreadResult(wxThreadEvent &evt){
switch(evt.GetInt()){
case Dao::ID_FOO:
MyModel m=evt.GetPayload<MyModel>();
// Do stuff
break;
//case ID_BAR:
// ...
}
}