Changeset 184229 in webkit


Ignore:
Timestamp:
May 12, 2015 6:47:15 PM (9 years ago)
Author:
mark.lam@apple.com
Message:

Windows: Cannot use HANDLE from GetCurrentThread() to get the CONTEXT of another thread.
https://bugs.webkit.org/show_bug.cgi?id=144924

Reviewed by Alex Christensen.

The present stack scanning code in the Windows port is expecting that the
GetCurrentThread() API will provide a unique HANDLE for each thread. The code
then saves and later uses that HANDLE with GetThreadContext() to get the
runtime state of the target thread from the GC thread. According to
https://msdn.microsoft.com/en-us/library/windows/desktop/ms683182(v=vs.85).aspx,
GetCurrentThread() does not provide this unique HANDLE that we expect:

"The function cannot be used by one thread to create a handle that can
be used by other threads to refer to the first thread. The handle is
always interpreted as referring to the thread that is using it. A
thread can create a "real" handle to itself that can be used by other
threads, or inherited by other processes, by specifying the pseudo
handle as the source handle in a call to the DuplicateHandle function."

As a result of this, GetCurrentThread() always returns the same HANDLE value, and
we end up never scanning the stacks of other threads because we wrongly think that
they are all equal (in identity) to the scanning thread. This, in turn, results
in crashes due to objects that are incorrectly collected.

The fix is to call DuplicateHandle() to create a HANDLE that we can use. The
MachineThreads::Thread class already accurately tracks the period of time when
we need that HANDLE for the VM. Hence, the life-cycle of the HANDLE can be tied
to the life-cycle of the MachineThreads::Thread object for the corresponding thread.

  • heap/MachineStackMarker.cpp:

(JSC::getCurrentPlatformThread):
(JSC::MachineThreads::Thread::Thread):
(JSC::MachineThreads::Thread::~Thread):
(JSC::MachineThreads::Thread::suspend):
(JSC::MachineThreads::Thread::resume):
(JSC::MachineThreads::Thread::getRegisters):

Location:
trunk/Source/JavaScriptCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r184220 r184229  
     12015-05-12  Mark Lam  <mark.lam@apple.com>
     2
     3        Windows: Cannot use HANDLE from GetCurrentThread() to get the CONTEXT of another thread.
     4        https://bugs.webkit.org/show_bug.cgi?id=144924
     5
     6        Reviewed by Alex Christensen.
     7
     8        The present stack scanning code in the Windows port is expecting that the
     9        GetCurrentThread() API will provide a unique HANDLE for each thread.  The code
     10        then saves and later uses that HANDLE with GetThreadContext() to get the
     11        runtime state of the target thread from the GC thread.  According to
     12        https://msdn.microsoft.com/en-us/library/windows/desktop/ms683182(v=vs.85).aspx,
     13        GetCurrentThread() does not provide this unique HANDLE that we expect:
     14
     15            "The function cannot be used by one thread to create a handle that can
     16            be used by other threads to refer to the first thread. The handle is
     17            always interpreted as referring to the thread that is using it. A
     18            thread can create a "real" handle to itself that can be used by other
     19            threads, or inherited by other processes, by specifying the pseudo
     20            handle as the source handle in a call to the DuplicateHandle function."
     21
     22        As a result of this, GetCurrentThread() always returns the same HANDLE value, and
     23        we end up never scanning the stacks of other threads because we wrongly think that
     24        they are all equal (in identity) to the scanning thread.  This, in turn, results
     25        in crashes due to objects that are incorrectly collected.
     26
     27        The fix is to call DuplicateHandle() to create a HANDLE that we can use.  The
     28        MachineThreads::Thread class already accurately tracks the period of time when
     29        we need that HANDLE for the VM.  Hence, the life-cycle of the HANDLE can be tied
     30        to the life-cycle of the MachineThreads::Thread object for the corresponding thread.
     31
     32        * heap/MachineStackMarker.cpp:
     33        (JSC::getCurrentPlatformThread):
     34        (JSC::MachineThreads::Thread::Thread):
     35        (JSC::MachineThreads::Thread::~Thread):
     36        (JSC::MachineThreads::Thread::suspend):
     37        (JSC::MachineThreads::Thread::resume):
     38        (JSC::MachineThreads::Thread::getRegisters):
     39
    1402015-05-12  Benjamin Poulain  <bpoulain@apple.com>
    241
  • trunk/Source/JavaScriptCore/heap/MachineStackMarker.cpp

    r184218 r184229  
    7373typedef mach_port_t PlatformThread;
    7474#elif OS(WINDOWS)
    75 typedef HANDLE PlatformThread;
     75typedef DWORD PlatformThread;
    7676#elif USE(PTHREADS)
    7777typedef pthread_t PlatformThread;
     
    152152    return pthread_mach_thread_np(pthread_self());
    153153#elif OS(WINDOWS)
    154     return GetCurrentThread();
     154    return GetCurrentThreadId();
    155155#elif USE(PTHREADS)
    156156    return pthread_self();
     
    177177        sigaddset(&mask, SigThreadSuspendResume);
    178178        pthread_sigmask(SIG_UNBLOCK, &mask, 0);
     179#elif OS(WINDOWS)
     180        ASSERT(platformThread == GetCurrentThreadId());
     181        bool isSuccessful =
     182            DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(),
     183                &platformThreadHandle, 0, FALSE, DUPLICATE_SAME_ACCESS);
     184        RELEASE_ASSERT(isSuccessful);
    179185#endif
    180186    }
    181187
    182188public:
     189    ~Thread()
     190    {
     191#if OS(WINDOWS)
     192        CloseHandle(platformThreadHandle);
     193#endif
     194    }
     195
    183196    static Thread* createForCurrentThread()
    184197    {
     
    229242    PlatformThread platformThread;
    230243    void* stackBase;
     244#if OS(WINDOWS)
     245    HANDLE platformThreadHandle;
     246#endif
    231247};
    232248
     
    336352    return result == KERN_SUCCESS;
    337353#elif OS(WINDOWS)
    338     bool threadIsSuspended = (SuspendThread(platformThread) != (DWORD)-1);
     354    bool threadIsSuspended = (SuspendThread(platformThreadHandle) != (DWORD)-1);
    339355    ASSERT(threadIsSuspended);
    340356    return threadIsSuspended;
     
    352368    thread_resume(platformThread);
    353369#elif OS(WINDOWS)
    354     ResumeThread(platformThread);
     370    ResumeThread(platformThreadHandle);
    355371#elif USE(PTHREADS)
    356372    pthread_kill(platformThread, SigThreadSuspendResume);
     
    397413#elif OS(WINDOWS)
    398414    regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
    399     GetThreadContext(platformThread, &regs);
     415    GetThreadContext(platformThreadHandle, &regs);
    400416    return sizeof(CONTEXT);
    401417#elif USE(PTHREADS)
Note: See TracChangeset for help on using the changeset viewer.