source: webkit/trunk/JavaScriptCore/wtf/ThreadIdentifierDataPthreads.cpp@ 65104

Last change on this file since 65104 was 53714, checked in by [email protected], 15 years ago

Fix the leak of ThreadIdentifiers in threadMap across threads.
https://bugs.webkit.org/show_bug.cgi?id=32689

Reviewed by Maciej Stachowiak.

JavaScriptCore:

Test is added to DumpRenderTree.mm.

  • Android.mk: Added file ThreadIdentifierDataPthreads.(h|cpp) to build.
  • Android.v8.wtf.mk: Ditto.
  • GNUmakefile.am: Ditto.
  • JavaScriptCore.gyp/JavaScriptCore.gyp: Ditto.
  • JavaScriptCore.gypi: Ditto.
  • JavaScriptCore.xcodeproj/project.pbxproj: Ditto.
  • wtf/ThreadIdentifierDataPthreads.cpp: Added. Contains custom implementation of thread-specific data that uses custom destructor.

(WTF::ThreadIdentifierData::~ThreadIdentifierData): Removes the ThreadIdentifier from the threadMap.
(WTF::ThreadIdentifierData::identifier):
(WTF::ThreadIdentifierData::initialize):
(WTF::ThreadIdentifierData::destruct): Custom thread-specific destructor. Resets the value for the key again to cause second invoke.
(WTF::ThreadIdentifierData::initializeKeyOnceHelper):
(WTF::ThreadIdentifierData::initializeKeyOnce): Need to use pthread_once since initialization may come on any thread(s).

  • wtf/ThreadIdentifierDataPthreads.h: Added.

(WTF::ThreadIdentifierData::ThreadIdentifierData):

  • wtf/Threading.cpp:

(WTF::threadEntryPoint): Move initializeCurrentThreadInternal to after the lock to make

sure it is invoked when ThreadIdentifier is already established.

  • wtf/Threading.h: Rename setThreadNameInternal -> initializeCurrentThreadInternal since it does more then only set the name now.
  • wtf/ThreadingNone.cpp:

(WTF::initializeCurrentThreadInternal): Ditto.

  • wtf/ThreadingWin.cpp:

(WTF::initializeCurrentThreadInternal): Ditto.
(WTF::initializeThreading): Ditto.

  • wtf/gtk/ThreadingGtk.cpp:

(WTF::initializeCurrentThreadInternal): Ditto.

  • wtf/qt/ThreadingQt.cpp:

(WTF::initializeCurrentThreadInternal): Ditto.

  • wtf/ThreadingPthreads.cpp:

(WTF::establishIdentifierForPthreadHandle):
(WTF::clearPthreadHandleForIdentifier): Make it not 'static' so the ~ThreadIdentifierData() in another file can call it.
(WTF::initializeCurrentThreadInternal): Set the thread-specific data. The ThreadIdentifier is already established by creating thread.
(WTF::waitForThreadCompletion): Remove call to clearPthreadHandleForIdentifier(threadID) since it is now done in ~ThreadIdentifierData().
(WTF::detachThread): Ditto.
(WTF::currentThread): Use the thread-specific data to get the ThreadIdentifier. It's many times faster then Mutex-protected iteration through the map.

Also, set the thread-specific data if called first time on the thread.

WebKitTools:

Add a new test to verify the ThreadIdentifiers are not reused across threads.
The test runs in the beginning of DumpRenderTree and spawns 2 non-WTF treads sequentially,
waiting for the previous thread to terminate before starting the next.
The treads use WTF::currentThread() in their thread function. Without a fix, this
causes both threads to have the same ThreadIdentifier which triggers ASSERT in thread function.
It also starts another thread using WTF. Without the fix, this finds pthread handle from previous
threads in the WTF threadMap and asserts in WTF::establishIdentifierForPthreadHandle().
The test practically does not affect the DRT run time because the threads end immediately.

  • DumpRenderTree/mac/DumpRenderTree.mm:

(runThread): Test thread function.
(testThreadIdentifierMap):
(dumpRenderTree):

File size: 3.1 KB
Line 
1/*
2 * Copyright (C) 2009 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include "config.h"
32
33#if USE(PTHREADS)
34
35#include "ThreadIdentifierDataPthreads.h"
36
37#include "Threading.h"
38
39namespace WTF {
40
41pthread_key_t ThreadIdentifierData::m_key;
42
43void clearPthreadHandleForIdentifier(ThreadIdentifier);
44
45ThreadIdentifierData::~ThreadIdentifierData()
46{
47 clearPthreadHandleForIdentifier(m_identifier);
48}
49
50ThreadIdentifier ThreadIdentifierData::identifier()
51{
52 initializeKeyOnce();
53 ThreadIdentifierData* threadIdentifierData = static_cast<ThreadIdentifierData*>(pthread_getspecific(m_key));
54
55 return threadIdentifierData ? threadIdentifierData->m_identifier : 0;
56}
57
58void ThreadIdentifierData::initialize(ThreadIdentifier id)
59{
60 ASSERT(!identifier());
61
62 initializeKeyOnce();
63 pthread_setspecific(m_key, new ThreadIdentifierData(id));
64}
65
66void ThreadIdentifierData::destruct(void* data)
67{
68 ThreadIdentifierData* threadIdentifierData = static_cast<ThreadIdentifierData*>(data);
69 ASSERT(threadIdentifierData);
70
71 if (threadIdentifierData->m_isDestroyedOnce) {
72 delete threadIdentifierData;
73 return;
74 }
75
76 threadIdentifierData->m_isDestroyedOnce = true;
77 // Re-setting the value for key causes another destruct() call after all other thread-specific destructors were called.
78 pthread_setspecific(m_key, threadIdentifierData);
79}
80
81void ThreadIdentifierData::initializeKeyOnceHelper()
82{
83 if (pthread_key_create(&m_key, destruct))
84 CRASH();
85}
86
87void ThreadIdentifierData::initializeKeyOnce()
88{
89 static pthread_once_t onceControl = PTHREAD_ONCE_INIT;
90 if (pthread_once(&onceControl, initializeKeyOnceHelper))
91 CRASH();
92}
93
94} // namespace WTF
95
96#endif // USE(PTHREADS)
97
Note: See TracBrowser for help on using the repository browser.