Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ResumeThread sometimes doesn't wake threads

I have two functions in my C++: one to suspend, one to resume threads. In some situations I need to stop all thread but current and it's ok, but when I must resume the threads, sometimes it doesn't work and I don't no why. See the method:

void CDatabaseMonitor::ResumeAllThreads() 
{
    DWORD dwCurProc = GetCurrentProcessId();
    HANDLE hCurProc = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);

    if (hCurProc != INVALID_HANDLE_VALUE)
    {
        THREADENTRY32 te = {0};
        te.dwSize = sizeof(te);

        if (Thread32First(hCurProc, &te))
        {
            do
            {
                if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(te.th32OwnerProcessID))
                {
                    if (te.th32ThreadID != m_currentThreadId && te.th32OwnerProcessID == dwCurProc)
                    {
                        HANDLE thread = ::OpenThread(THREAD_ALL_ACCESS, FALSE, te.th32ThreadID);

                        if (thread != NULL)
                        {
                            ResumeThread(thread);
                            CloseHandle(thread);
                        }
                    }
                }

                te.dwSize = sizeof(te);
            }
            while (Thread32Next(hCurProc, &te));
        }

        CloseHandle(hCurProc);
    }
}

Is there something worng with the code above? Is there any way to force a thread to wake? Thanks in advance.

like image 987
anc Avatar asked Dec 07 '25 05:12

anc


1 Answers

You can't use SuspendThread/ResumeThread this way. As the docs say:

This function is primarily designed for use by debuggers. It is not intended to be used for thread synchronization. Calling SuspendThread on a thread that owns a synchronization object, such as a mutex or critical section, can lead to a deadlock if the calling thread tries to obtain a synchronization object owned by a suspended thread. To avoid this situation, a thread within an application that is not a debugger should signal the other thread to suspend itself. The target thread must be designed to watch for this signal and respond appropriately.

The main problem is this -- there is basically nothing you can do while the thread is suspended. If the thread was holding a lock you require, you will deadlock waiting for it to release it. And you have no way to know what locks that thread might have because threads can be hijacked at arbitrary points to do arbitrary work by a number of mechanisms used by libraries.

You will never get this to work, and whatever problem you're trying to solve by suspending threads you should instead solve some other, sensible way.

The canonical answer to the question, "How do I safely suspend/resume a thread from another thread in the same process?" is "With that thread's cooperation, use whatever mechanism that thread supports. Without that thread's cooperation, it cannot be done safely."

Any time you feel like you need to "reach in" from the outside to make a thread do the right thing, you should step back and rethink your design. The thread should already be coded to do what, and only what, you want it to do. If the thread needs to suspend, it should be coded to suspend itself. If you have to reach in to make it do what you want or not do what you don't want, you coded it wrong in the first place and should fix it. All the threads in a process must cooperate.

like image 60
David Schwartz Avatar answered Dec 09 '25 19:12

David Schwartz