Reputation: 32197
On msvc if you try to join a thread that's not joinable it will call abort. So you have to check if the thread is joinable before calling join but this in it self is a race condition.
void BaseThread::join()
{
auto thread = m_pPrivates->m_pThread;
if (!thread)
return;
if (thread->get_id() != std::thread::id() && thread->joinable())
thread->join();
}
Is there away to stop the run time calling abort if a thread is not joinable or a better way to do this?
.
.
.
Edit:
So this is the function that handles thread close in visual studio run time.
int _Thrd_join(_Thrd_t thr, int *code)
{ /* return exit code when thread terminates */
unsigned long res;
if (WaitForSingleObject(thr._Hnd, INFINITE) == WAIT_FAILED || GetExitCodeThread(thr._Hnd, &res) == 0)
return (_Thrd_error);
if (code)
*code = (int)res;
return (CloseHandle(thr._Hnd) == 0 ? _Thrd_error : _Thrd_success);
}
The last line (CloseHandle) is throwing this exception:
Unhandled exception at 0x7750BCEC (ntdll.dll) in desura.exe: 0xC0000008: An invalid handle was specified. Which then crashes the app
Upvotes: 4
Views: 2122
Reputation: 4591
It's not inherently a race condition. A thread remains joinable until it is either joined, detached, or moved-from. These are all things your program has control over, and if another thread is doing one of these things asynchronously to the thread you're trying to join, you obviously have to synchronize. Usually, it's not, though, and you're the owner/manager of the thread.
Note that just because a thread finishes execution, that does not make it unjoinable. In fact, even if you can guarantee that a thread has completed execution, you still have to join with it (or detach it, etc.) to prevent terminate()
from being called.
Upvotes: 6