Title: [184302] branches/safari-600.5.17-branch/Source/_javascript_Core

Diff

Modified: branches/safari-600.5.17-branch/Source/_javascript_Core/ChangeLog (184301 => 184302)


--- branches/safari-600.5.17-branch/Source/_javascript_Core/ChangeLog	2015-05-13 20:10:18 UTC (rev 184301)
+++ branches/safari-600.5.17-branch/Source/_javascript_Core/ChangeLog	2015-05-13 20:40:21 UTC (rev 184302)
@@ -1,3 +1,49 @@
+2015-05-13  Babak Shafiei  <[email protected]>
+
+        Merge r184229.
+
+    2015-05-12  Mark Lam  <[email protected]>
+
+            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::MachineThreads::Thread::Thread):
+        (JSC::MachineThreads::Thread::~Thread):
+        (JSC::getCurrentPlatformThread):
+        (JSC::suspendThread):
+        (JSC::resumeThread):
+        (JSC::getPlatformThreadRegisters):
+        (JSC::MachineThreads::gatherFromOtherThread):
+        (JSC::MachineThreads::gatherConservativeRoots):
+        * heap/MachineStackMarker.h:
+
 2015-04-07  Babak Shafiei  <[email protected]>
 
         Merge r181628.

Modified: branches/safari-600.5.17-branch/Source/_javascript_Core/heap/MachineStackMarker.cpp (184301 => 184302)


--- branches/safari-600.5.17-branch/Source/_javascript_Core/heap/MachineStackMarker.cpp	2015-05-13 20:10:18 UTC (rev 184301)
+++ branches/safari-600.5.17-branch/Source/_javascript_Core/heap/MachineStackMarker.cpp	2015-05-13 20:40:21 UTC (rev 184302)
@@ -84,7 +84,7 @@
 #if OS(DARWIN)
 typedef mach_port_t PlatformThread;
 #elif OS(WINDOWS)
-typedef HANDLE PlatformThread;
+typedef DWORD PlatformThread;
 #elif USE(PTHREADS)
 typedef pthread_t PlatformThread;
 static const int SigThreadSuspendResume = SIGUSR2;
@@ -119,12 +119,26 @@
         sigemptyset(&mask);
         sigaddset(&mask, SigThreadSuspendResume);
         pthread_sigmask(SIG_UNBLOCK, &mask, 0);
+#elif OS(WINDOWS)
+        ASSERT(platformThread == GetCurrentThreadId());
+        bool isSuccessful = DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &platformThreadHandle, 0, FALSE, DUPLICATE_SAME_ACCESS);
+        RELEASE_ASSERT(isSuccessful);
 #endif
     }
 
+    ~Thread()
+    {
+#if OS(WINDOWS)
+        CloseHandle(platformThreadHandle);
+#endif
+    }
+
     Thread* next;
     PlatformThread platformThread;
     void* stackBase;
+#if OS(WINDOWS)
+    HANDLE platformThreadHandle;
+#endif
 };
 
 MachineThreads::MachineThreads(Heap* heap)
@@ -155,7 +169,7 @@
 #if OS(DARWIN)
     return pthread_mach_thread_np(pthread_self());
 #elif OS(WINDOWS)
-    return GetCurrentThread();
+    return GetCurrentThreadId();
 #elif USE(PTHREADS)
     return pthread_self();
 #endif
@@ -240,31 +254,31 @@
     conservativeRoots.add(stackBegin, stackEnd, jitStubRoutines, codeBlocks);
 }
 
-static inline bool suspendThread(const PlatformThread& platformThread)
+static inline bool suspendThread(MachineThreads::Thread* thread)
 {
 #if OS(DARWIN)
-    kern_return_t result = thread_suspend(platformThread);
+    kern_return_t result = thread_suspend(thread->platformThread);
     return result == KERN_SUCCESS;
 #elif OS(WINDOWS)
-    bool threadIsSuspended = (SuspendThread(platformThread) != (DWORD)-1);
+    bool threadIsSuspended = (SuspendThread(thread->platformThreadHandle) != (DWORD)-1);
     ASSERT(threadIsSuspended);
     return threadIsSuspended;
 #elif USE(PTHREADS)
-    pthread_kill(platformThread, SigThreadSuspendResume);
+    pthread_kill(thread->platformThread, SigThreadSuspendResume);
     return true;
 #else
 #error Need a way to suspend threads on this platform
 #endif
 }
 
-static inline void resumeThread(const PlatformThread& platformThread)
+static inline void resumeThread(MachineThreads::Thread* thread)
 {
 #if OS(DARWIN)
-    thread_resume(platformThread);
+    thread_resume(thread->platformThread);
 #elif OS(WINDOWS)
-    ResumeThread(platformThread);
+    ResumeThread(thread->platformThreadHandle);
 #elif USE(PTHREADS)
-    pthread_kill(platformThread, SigThreadSuspendResume);
+    pthread_kill(thread->platformThread, SigThreadSuspendResume);
 #else
 #error Need a way to resume threads on this platform
 #endif
@@ -298,7 +312,7 @@
 #error Need a thread register struct for this platform
 #endif
 
-static size_t getPlatformThreadRegisters(const PlatformThread& platformThread, PlatformThreadRegisters& regs)
+static size_t getPlatformThreadRegisters(MachineThreads::Thread* thread, PlatformThreadRegisters& regs)
 {
 #if OS(DARWIN)
 
@@ -324,7 +338,7 @@
 #error Unknown Architecture
 #endif
 
-    kern_return_t result = thread_get_state(platformThread, flavor, (thread_state_t)&regs, &user_count);
+    kern_return_t result = thread_get_state(thread->platformThread, flavor, (thread_state_t)&regs, &user_count);
     if (result != KERN_SUCCESS) {
         WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 
                             "_javascript_ garbage collection failed because thread_get_state returned an error (%d). This is probably the result of running inside Rosetta, which is not supported.", result);
@@ -335,18 +349,18 @@
 
 #elif OS(WINDOWS)
     regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
-    GetThreadContext(platformThread, &regs);
+    GetThreadContext(thread->platformThreadHandle, &regs);
     return sizeof(CONTEXT);
 #elif USE(PTHREADS)
     pthread_attr_init(&regs);
 #if HAVE(PTHREAD_NP_H) || OS(NETBSD)
 #if !OS(OPENBSD)
     // e.g. on FreeBSD 5.4, [email protected]
-    pthread_attr_get_np(platformThread, &regs);
+    pthread_attr_get_np(thread->platformThread, &regs);
 #endif
 #else
     // FIXME: this function is non-portable; other POSIX systems may have different np alternatives
-    pthread_getattr_np(platformThread, &regs);
+    pthread_getattr_np(thread->platformThread, &regs);
 #endif
     return 0;
 #else
@@ -434,7 +448,7 @@
 void MachineThreads::gatherFromOtherThread(ConservativeRoots& conservativeRoots, Thread* thread, JITStubRoutineSet& jitStubRoutines, CodeBlockSet& codeBlocks)
 {
     PlatformThreadRegisters regs;
-    size_t regSize = getPlatformThreadRegisters(thread->platformThread, regs);
+    size_t regSize = getPlatformThreadRegisters(thread, regs);
 
     conservativeRoots.add(static_cast<void*>(&regs), static_cast<void*>(reinterpret_cast<char*>(&regs) + regSize), jitStubRoutines, codeBlocks);
 
@@ -469,7 +483,7 @@
         Thread* previousThread = nullptr;
         for (Thread* thread = m_registeredThreads; thread; index++) {
             if (!equalThread(thread->platformThread, currentPlatformThread)) {
-                bool success = suspendThread(thread->platformThread);
+                bool success = suspendThread(thread);
 #if OS(DARWIN)
                 if (!success) {
                     if (!numberOfThreads) {
@@ -519,7 +533,7 @@
 
         for (Thread* thread = m_registeredThreads; thread; thread = thread->next) {
             if (!equalThread(thread->platformThread, currentPlatformThread))
-                resumeThread(thread->platformThread);
+                resumeThread(thread);
         }
 
 #ifndef NDEBUG

Modified: branches/safari-600.5.17-branch/Source/_javascript_Core/heap/MachineStackMarker.h (184301 => 184302)


--- branches/safari-600.5.17-branch/Source/_javascript_Core/heap/MachineStackMarker.h	2015-05-13 20:10:18 UTC (rev 184301)
+++ branches/safari-600.5.17-branch/Source/_javascript_Core/heap/MachineStackMarker.h	2015-05-13 20:40:21 UTC (rev 184302)
@@ -47,11 +47,11 @@
         JS_EXPORT_PRIVATE void makeUsableFromMultipleThreads();
         JS_EXPORT_PRIVATE void addCurrentThread(); // Only needs to be called by clients that can use the same heap from multiple threads.
 
+        class Thread;
+
     private:
         void gatherFromCurrentThread(ConservativeRoots&, JITStubRoutineSet&, CodeBlockSet&, void* stackCurrent, RegisterState& registers);
 
-        class Thread;
-
         static void removeThread(void*);
         void removeCurrentThread();
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to