Crash with boost::thread Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
mspoerr
Experienced Solver
Experienced Solver
Posts: 50
Joined: Sat Mar 15, 2008 9:17 pm

Crash with boost::thread

Post by mspoerr » Mon Jun 29, 2009 3:20 pm

Hello,

I am using wxwidgets together with boost::thread. The Thread is a worker thread which sends some Events to the GUI:

Thread creation:

Code: Select all

thrd = boost::thread(boost::bind(workerFunction,this));
Send Message to the GUI:

Code: Select all

wxPostEvent(loWindow, event);
wxSafeYield();
Under Windows I don't see any problems, but when starting the application under Linux (Ubuntu 8.10), it stops with the following error message:
_XCBUnlockDisplay: Assertion `xcb_get_request_sent(dpy->xcb->connection) == dpy->request' failed.
Aborted
What am I missing? When the workerFunction is not started in a thread, it works without problems.
I don't touch the GUI directly - only via wxPostevent().

Thanks,
/mspoerr

User avatar
doublemax
Moderator
Moderator
Posts: 15259
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Post by doublemax » Mon Jun 29, 2009 3:55 pm

i don't know if that is the reason for your problem, but calling wxSafeYield from a secondary thread doesn't look right.
Use the source, Luke!

mspoerr
Experienced Solver
Experienced Solver
Posts: 50
Joined: Sat Mar 15, 2008 9:17 pm

Post by mspoerr » Mon Jun 29, 2009 4:07 pm

when I don't do this, the app also crashes in Windows and earlier in Linux. I thought I have to use it, becasue in the documentation I found the following hint:
Yields control to pending messages in the windowing system. This can be useful, for example, when a time-consuming process writes to a text window. Without an occasional yield, the text window will not be updated properly, and on systems with cooperative multitasking, such as Windows 3.1 other processes will not respond.
Maybe I have to use it in the Log Window?

Thanks,
/mspoerr

User avatar
doublemax
Moderator
Moderator
Posts: 15259
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Post by doublemax » Mon Jun 29, 2009 4:14 pm

mspoerr wrote:I thought I have to use it, becasue in the documentation I found the following hint:
Yields control to pending messages in the windowing system. This can be useful, for example, when a time-consuming process writes to a text window. Without an occasional yield, the text window will not be updated properly, and on systems with cooperative multitasking, such as Windows 3.1 other processes will not respond.
this applies when you have a long-running task in the main thread, then you can call Yield() to give the application the chance to process events and update its gui. In a secondary thread you don't need it (because the main thread is not blocked) and it's probably bad because it would start processing events in the secondary thread.
when I don't do this, the app also crashes in Windows and earlier in Linux.
then i think the problem lies somewhere else.
Maybe I have to use it in the Log Window?
i don't know what log window you're talking about
Use the source, Luke!

mspoerr
Experienced Solver
Experienced Solver
Posts: 50
Joined: Sat Mar 15, 2008 9:17 pm

Post by mspoerr » Mon Jun 29, 2009 6:03 pm

this applies when you have a long-running task in the main thread, then you can call Yield() to give the application the chance to process events and update its gui. In a secondary thread you don't need it (because the main thread is not blocked) and it's probably bad because it would start processing events in the secondary thread.
oh -ok.

With Log Window I mean a text window, where the events from the thread are posted -> Thread runs and is very chatty. All output is sent via wxPostEvent to the Log Window, where it is displayed. What would be a good solution for this? For what do I need to take care of?

Thanks,
mspoerr

User avatar
doublemax
Moderator
Moderator
Posts: 15259
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Post by doublemax » Mon Jun 29, 2009 6:29 pm

first you should find out if this is really the cause for the crash. Does everything work fine if you comment out the wxPostEvent call?

What kind of event do you send? A custom event or a standard wxCommandEvent? wxString is not thread-safe, so sending strings using wxCommandEvent::SetString is a potential reason for your crash.

But then again, these kind of crashes are usually more random, so it's possible that your problem is really somewhere else. Do you have a backtrace?
Use the source, Luke!

mspoerr
Experienced Solver
Experienced Solver
Posts: 50
Joined: Sat Mar 15, 2008 9:17 pm

Post by mspoerr » Mon Jun 29, 2009 8:15 pm

when not posting the event, the application doesn't crash. I use a wxCommandEvent with a string:

Code: Select all

void Ersetzer::schreibeLog(int type, string logEintrag, int farbe, int format, int groesse)
{
	if (logAusgabe != NULL)
	{
		evtData evtDat;
		evtDat.farbe = farbe;
		evtDat.format = format;
		evtDat.groesse = groesse;
		evtDat.logEintrag = logEintrag;
		evtDat.type = type;
		
		wxCommandEvent event(wkEVT_SCHREIBELOG);
		event.SetClientData(&evtDat);
		wxPostEvent(logAusgabe, event);

		//wxSafeYield();
	}
}
How should I change this to make it work?

Thanks,
mspoerr

User avatar
doublemax
Moderator
Moderator
Posts: 15259
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Post by doublemax » Mon Jun 29, 2009 8:31 pm

you should have posted that code earlier, this can't work at all. You're only writing the pointer &evtDat into the event data, the data itself is a local variable, so the pointer will be invalid when the event gets processed.

You should create a custom event for this purpose.
http://docs.wxwidgets.org/stable/wx_eve ... stomevents
Use the source, Luke!

mspoerr
Experienced Solver
Experienced Solver
Posts: 50
Joined: Sat Mar 15, 2008 9:17 pm

Post by mspoerr » Mon Jun 29, 2009 8:49 pm

You're only writing the pointer &evtDat into the event data, the data itself is a local variable, so the pointer will be invalid when the event gets processed.
sounds reasonable
You should create a custom event for this purpose.
What is the advantage of a custom event?

Thanks,
mspoerr

User avatar
doublemax
Moderator
Moderator
Posts: 15259
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Post by doublemax » Mon Jun 29, 2009 8:55 pm

you need an own event class if you want to send more complex data. For that it's important to overwrite wxEvent::Clone() with your own version that makes sure all the data is copied correctly.
Use the source, Luke!

mspoerr
Experienced Solver
Experienced Solver
Posts: 50
Joined: Sat Mar 15, 2008 9:17 pm

Post by mspoerr » Mon Jun 29, 2009 8:57 pm

ok - thank you very much. I will try and come back later ;)

/mspoerr

Frank
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 211
Joined: Sat Jan 01, 2005 6:19 pm

Post by Frank » Tue Jun 30, 2009 11:08 am

Since you're using Boost, maybe I can help you out with a generic event, wich uses boost::any, so you can post every data you want:

Code: Select all

class DataEvent : public wxEvent
{
   boost::any data;

public:
   DataEvent () : wxEvent(0, wxEVT_DATA) { }
   DataEvent (const boost::any& data) : wxEvent(0, wxEVT_DATA), data(data) {  }
   ~wxGDDataEvent () { }

   wxEvent* Clone () const { return new DataEvent(*this); }

   void SetData (const boost::any& data) { this->data = data; }
   boost::any GetData () const { return data; }

   template<typename T> T GetData () const { return boost::any_cast<T>(data); }
};

mspoerr
Experienced Solver
Experienced Solver
Posts: 50
Joined: Sat Mar 15, 2008 9:17 pm

Post by mspoerr » Tue Jun 30, 2009 6:37 pm

Thank you for the hint. I will check it out.

/mspoerr

mspoerr
Experienced Solver
Experienced Solver
Posts: 50
Joined: Sat Mar 15, 2008 9:17 pm

Post by mspoerr » Tue Jun 30, 2009 8:54 pm

Stupid question: How to use the GetData() function? Would you please so kind to post a sample?
I always get an compiler error: 'conversion' : cannot convert from 'boost::any' to 'std::string'

Thanks,
mspoerr

Frank
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 211
Joined: Sat Jan 01, 2005 6:19 pm

Post by Frank » Wed Jul 01, 2009 2:53 pm

You can either use boost::any_cast or the template-function:

Code: Select all

// Option 1
std::string str = event.GetData<std::string>();

// Option 2
boost::any data = event.GetData();
std::string str = boost::any_cast<std::string>(data);

// When you need to check the type of the data you can use typeid:

if (data.type() == typeid(std::string)) // ...

Post Reply