+ // have to declare this before pthread_cleanup_push() which defines a
+ // block!
+ bool dontRunAtAll;
+
+#if HAVE_THREAD_CLEANUP_FUNCTIONS
+ // install the cleanup handler which will be called if the thread is
+ // cancelled
+ pthread_cleanup_push(wxPthreadCleanup, thread);
+#endif // HAVE_THREAD_CLEANUP_FUNCTIONS
+
+ // wait for the semaphore to be posted from Run()
+ pthread->m_semRun.Wait();
+
+ // test whether we should run the run at all - may be it was deleted
+ // before it started to Run()?
+ {
+ wxCriticalSectionLocker lock(thread->m_critsect);
+
+ dontRunAtAll = pthread->GetState() == STATE_NEW &&
+ pthread->WasCancelled();
+ }
+
+ if ( !dontRunAtAll )
+ {
+ // call the main entry
+ wxLogTrace(TRACE_THREADS, _T("Thread %ld about to enter its Entry()."),
+#ifdef __VMS
+ (long long)pthread->GetId());
+#else
+ (long)pthread->GetId());
+#endif
+
+ pthread->m_exitcode = thread->Entry();
+
+ wxLogTrace(TRACE_THREADS, _T("Thread %ld Entry() returned %lu."),
+#ifdef __VMS
+ (long long)pthread->GetId(), (unsigned long)pthread->m_exitcode);
+#else
+ (long)pthread->GetId(), (unsigned long)pthread->m_exitcode);
+#endif
+
+ {
+ wxCriticalSectionLocker lock(thread->m_critsect);
+
+ // change the state of the thread to "exited" so that
+ // wxPthreadCleanup handler won't do anything from now (if it's
+ // called before we do pthread_cleanup_pop below)
+ pthread->SetState(STATE_EXITED);
+ }
+ }
+
+ // NB: at least under Linux, pthread_cleanup_push/pop are macros and pop
+ // contains the matching '}' for the '{' in push, so they must be used
+ // in the same block!
+#if HAVE_THREAD_CLEANUP_FUNCTIONS
+ // remove the cleanup handler without executing it
+ pthread_cleanup_pop(FALSE);
+#endif // HAVE_THREAD_CLEANUP_FUNCTIONS
+
+ if ( dontRunAtAll )
+ {
+ // FIXME: deleting a possibly joinable thread here???
+ delete thread;
+
+ return EXITCODE_CANCELLED;
+ }
+ else
+ {
+ // terminate the thread
+ thread->Exit(pthread->m_exitcode);
+
+ wxFAIL_MSG(wxT("wxThread::Exit() can't return."));