Page 1 of 1

Weird wxThread problem with Delete() and Wait() under WXMSW

Posted: Tue Aug 16, 2005 10:39 pm
by darryl242
wx-masters,

I've used wxThread with Windows before (wx2.4) without a problem. I'm working on a new project using wx2.6.1 and I'm having a problem where Delete() and Wait() are returning "invalid handle". I have put together a very small example that illustrates the problem (at least on my setup).

OS: Windows XP Home Edition Version 2002 Service Pack 2
Compiler: Visual C++ 6.0 Service Pack 5
Release build flags: NDEBUG,WIN32,_WINDOWS,WINVER=0x0400,UNICODE,_UNICODE
Libraries: kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib rpcrt4.lib winmm.lib wsock32.lib

I can attach my wx setup.h if required (it's pretty much stock though).

The example test code:

Code: Select all

#include <wx/setup.h>
#include <wx/wx.h>
#include <wx/thread.h>
#include <wx/log.h>

typedef void *ExitCode;

class myThread : public wxThread
{
public:
	myThread() : wxThread(wxTHREAD_JOINABLE) {}
	ExitCode Entry();
};

ExitCode myThread::Entry()
{
	while(!TestDestroy())
	{
		wxLogMessage(wxT("thread tick."));
		Sleep(1000);
	}

	return NULL;
}

class myFrame : public wxFrame
{
public:
	myFrame();
	~myFrame();

private:
	myThread *thread;
};

myFrame::myFrame() : wxFrame(NULL, wxID_ANY,
	wxT("Frame"), wxDefaultPosition, wxSize(320, 240))
{
	thread = new myThread();

	if(thread)
	{
		wxThreadError error;

		if((error = thread->Create()) == wxTHREAD_NO_ERROR)
			error = thread->Run();

		if(error == wxTHREAD_NO_ERROR)
			wxLogMessage(wxT("thread started."));
		else
			wxLogMessage(wxT("thread creation error."));
	}

	Centre(); Show(true);
}

myFrame::~myFrame()
{
	if(thread)
	{
		wxLogMessage(wxT("thread->Delete()..."));
		thread->Delete();
		wxLogMessage(wxT("thread->Wait()..."));
		thread->Wait();
		wxLogMessage(wxT("delete thread..."));
		delete thread;
	}

	wxLogMessage(wxT("frame destroyed."));
}

class myApp : public wxApp
{
public:
	bool OnInit();
	int OnExit();

private:
	wxLogWindow *log;
};

DECLARE_APP(myApp)
IMPLEMENT_APP(myApp)

bool myApp::OnInit()
{
	log = new wxLogWindow(NULL, wxT("Log"), true, false);
	myFrame *frame;
	if(!(frame = new myFrame)) return false;
	SetTopWindow(frame);

	return true;
}

int myApp::OnExit()
{
	return wxApp::OnExit();
}
The output from the above code:

Code: Select all

18:16:31: thread started.
18:16:31: thread tick.
18:16:32: thread tick.
18:16:33: thread tick.
18:16:34: thread tick.
18:16:35: thread->Delete()...
18:16:35: thread->Wait()...
18:16:35: Error: Can not wait for thread termination (error 6: the handle is invalid.)
18:16:35: Error: Can not terminate thread (error 6: the handle is invalid.)
18:16:35: delete thread...
18:16:35: frame destroyed.
Question is why do I get "handle is invalid"... This sample code works fine under wx2.6.1/Linux. Any ideas?

Thanks :)

Re: Weird wxThread problem with Delete() and Wait() under WX

Posted: Wed Aug 17, 2005 12:07 pm
by Ryan Norton
darryl242 wrote:Question is why do I get "handle is invalid"... This sample code works fine under wx2.6.1/Linux. Any ideas?

Thanks :)
You should just be able to call Wait() - the thread is always dead on MSW after delete IIRC.

Re: Weird wxThread problem with Delete() and Wait() under WX

Posted: Wed Aug 17, 2005 2:18 pm
by darryl242
Ryan Norton wrote: You should just be able to call Wait() - the thread is always dead on MSW after delete IIRC.
Oh, ok... Is that not what I'm doing though? What would you differently here? I'm calling Delete() then Wait()... Both of these result in errors. The interesting part is that Delete() actually does something right because the thread does break at TestDestroy(). Nothing ever works for me under Windows :(

Code: Select all

                thread->Delete();
                thread->Wait();
                delete thread; 
Thanks...

Posted: Wed Aug 17, 2005 6:58 pm
by darryl242
Strange... I just discovered that if I call Delete() but not Wait()... the "handle invalid" error messages go away. I guess I'll leave my code like that as it seems to work. Does anyone know if this is a bug or something specific to Windows? Should I update the wxThread entry on wxWiki? There is no mention of this behaviour anywhere that I've read.

Code: Select all

        thread->Delete();
        //thread->Wait(); BAD
        delete thread;
Thanks again - now I can move along...

Posted: Wed Aug 17, 2005 10:28 pm
by Ryan Norton
darryl242 wrote:Strange... I just discovered that if I call Delete() but not Wait()... the "handle invalid" error messages go away. I guess I'll leave my code like that as it seems to work. Does anyone know if this is a bug or something specific to Windows? Should I update the wxThread entry on wxWiki? There is no mention of this behaviour anywhere that I've read.

Code: Select all

        thread->Delete();
        //thread->Wait(); BAD
        delete thread;
Thanks again - now I can move along...
No - you need to call Delete OR Wait - both of them eventually delete the thread handle (but not the wxThread in the case of joinable threads).

Wait IIRC is the same as delete except it returns the exit code of the thread while Delete does not and its only for joinable threads

Posted: Thu Aug 18, 2005 12:41 am
by darryl242
Yes, you are correct... My tests confirmed that Wait() or Delete() work the same (with the exception you pointed out). Linux pthreads doesn't cause the same error, that's why I thought I had a clue :p

Thanks again!