Opened 5 years ago

Closed 5 years ago

#11501 closed defect (fixed)

Fixed deadlock with pthread-implemented wxThread deletion.

Reported by: talon_karrde Owned by:
Priority: normal Milestone:
Component: base Version: stable-latest
Keywords: wxThread deadlock pthread unix Cc:
Blocked By: Blocking:
Patch: yes

Description

A deadlock occurs if one wxThread waits for another wxThread to finish in its destructor. Here's a sample code which demonstrates that:

class WorkerThread : public wxThread
{
public:
    WorkerThread()
    {
        this->pHelperThread = new HelperThread(this);
        this->pHelperThread->Create();
        this->pHelperThread->Run();
    }

    ~WorkerThread()
    {
        {
            wxCriticalSectionLocker cs(this->HelperThreadCS);
            if(this->pHelperThread) this->pHelperThread->Delete();
        }

        for(;;)
        {
            {
                wxCriticalSectionLocker cs(this->HelperThreadCS);
                if(this->pHelperThread == NULL) break;
            }
            wxThread::Yield();
        }
    }

    wxThread *pHelperThread;
    wxCriticalSection HelperThreadCS;
};

class HelperThread : public wxThread
{
public:
    HelperThread(WorkerThread *pParentThread) { this->pParentThread =
pParentThread; }
    ~HelperThread()
    {
        wxCriticalSectionLocker cs(pParentThread->HelperThreadCS);
        pParentThread->pHelperThread = NULL;
    }

    WorkerThread *pParentThread;
};

If WorkerThread finishes before HelperThread it attempts to delete it in its dtor and then wait for it to finish. WorkerThread's dtor, however, is executed while gs_mutexDeleteThread is locked, and HelperThread must acquire this mutex in order to clean up before exiting, which results in a deadlock.
I've attached a patch which simply calls the deleted wxThread's dtor before acquiring the mutex.

Attachments (1)

pthread_deadlock.patch download (773 bytes) - added by talon_karrde 5 years ago.

Download all attachments as: .zip

Change History (3)

Changed 5 years ago by talon_karrde

comment:1 Changed 5 years ago by talon_karrde

  • Version set to 2.9-svn

comment:2 Changed 5 years ago by VZ

  • Resolution set to fixed
  • Status changed from new to closed

(In [62781]) Don't lock global mutex when deleting wxThread to avoid deadlocks.

Calling out the user-defined wxThread dtor while holding gs_mutexDeleteThread
lock is a bad idea as it may result in deadlocks if the dtor deletes another
thread. Only lock the mutex directly before manipulating the data it protects.

Thanks to Neno Ganchev.

Closes #11501.

Note: See TracTickets for help on using tickets.