WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
199857
[WTF] Thread::removeFromThreadGroup leaks weak pointers.
https://bugs.webkit.org/show_bug.cgi?id=199857
Summary
[WTF] Thread::removeFromThreadGroup leaks weak pointers.
Takashi Komori
Reported
2019-07-17 05:32:35 PDT
ThreadGroup's destructor calls Thread::removeFromThreadGroup and tries to remove its weak pointer from Thread.m_threadGroups. As the call is from destructor the instance of ThreadGroup is already released and the removing always fail. As a result, the size of m_thraeadGroups won't decrease.
Attachments
Patch
(1.26 KB, patch)
2019-07-17 05:40 PDT
,
Takashi Komori
no flags
Details
Formatted Diff
Diff
Patch
(1.35 KB, patch)
2019-07-17 05:56 PDT
,
Takashi Komori
no flags
Details
Formatted Diff
Diff
Patch
(6.33 KB, patch)
2019-08-06 00:02 PDT
,
Takashi Komori
no flags
Details
Formatted Diff
Diff
Patch
(6.29 KB, patch)
2019-08-06 00:29 PDT
,
Takashi Komori
no flags
Details
Formatted Diff
Diff
Patch
(6.33 KB, patch)
2019-08-09 00:53 PDT
,
Takashi Komori
no flags
Details
Formatted Diff
Diff
Patch
(6.33 KB, patch)
2019-08-09 01:52 PDT
,
Takashi Komori
no flags
Details
Formatted Diff
Diff
Show Obsolete
(5)
View All
Add attachment
proposed patch, testcase, etc.
Takashi Komori
Comment 1
2019-07-17 05:40:30 PDT
Created
attachment 374292
[details]
Patch
Takashi Komori
Comment 2
2019-07-17 05:56:47 PDT
Created
attachment 374293
[details]
Patch
Brent Fulgham
Comment 3
2019-07-26 18:09:18 PDT
Comment on
attachment 374293
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=374293&action=review
> Source/WTF/ChangeLog:8 > + This patch makes Thread::removeFromThreadGroup remove all released weak pointers.
Is it possible to make a unit test for this bug?
Yusuke Suzuki
Comment 4
2019-07-26 19:37:40 PDT
Comment on
attachment 374293
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=374293&action=review
Nice catch! Discussed with Mark about whether this works with the current protocol of ThreadGroup and Thread, and we think that the key is that we should remove ThreadGroup unconditionally without using `weakPtr.lock()`. To achieve it simply with O(1), I commented about the HashMap based approach here. Does it seem good for you too?
> Source/WTF/wtf/Threading.cpp:259 > return sharedPtr.get() == &threadGroup; > return false; > });
Nice catch! I think the key is that, if we can just remove threadGroup unconditionally from this list, it should work. So, ideally, the code should be like, return &threadGroup == weakPtr.get(); Then it works. But the problem is that std::weak_ptr does not have an original raw pointer. So, can you change the code like, 1. Instead of holding a Vector<std::weak_ptr<ThreadGroup>>, let's hold HashMap<ThreadGroup*, std::weak_ptr<ThreadGroup>> 2. Remove the entry from that hash map in this function 3. In L214, iterate the hash map and collect shared_ptr from the value's weak_ptr Or, another simple way is that holding struct { ThreadGroup* threadGroup; std::weak_ptr<ThreadGroup> weakPtr } in a Vector, but I think HashMap one is better.
Yusuke Suzuki
Comment 5
2019-07-26 19:41:48 PDT
Comment on
attachment 374293
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=374293&action=review
>> Source/WTF/ChangeLog:8 >> + This patch makes Thread::removeFromThreadGroup remove all released weak pointers. > > Is it possible to make a unit test for this bug?
I think we can test it. Can you add a test to Tools/TestWebKitAPI/Tests/WTF/ThreadGroup.cpp? We can test it like, 1. Create a ThreadGroup 2. Add many Threads 3. Keep Threads live by using condition variable 4. Destroy ThreadGroup 5. Check the count of ThreadGroups of each Thread To get the value of (5), we need a method in Thread like, unsigned Thread::numberOfThreadGroups() { auto locker = holdLock(m_mutex); return m_threadGroups.size(); }
Takashi Komori
Comment 6
2019-08-01 01:30:34 PDT
(In reply to Yusuke Suzuki from
comment #5
)
> Comment on
attachment 374293
[details]
> Patch > > View in context: >
https://bugs.webkit.org/attachment.cgi?id=374293&action=review
> > >> Source/WTF/ChangeLog:8 > >> + This patch makes Thread::removeFromThreadGroup remove all released weak pointers. > > > > Is it possible to make a unit test for this bug? > > I think we can test it. Can you add a test to > Tools/TestWebKitAPI/Tests/WTF/ThreadGroup.cpp? > We can test it like, > > 1. Create a ThreadGroup > 2. Add many Threads > 3. Keep Threads live by using condition variable > 4. Destroy ThreadGroup > 5. Check the count of ThreadGroups of each Thread > > To get the value of (5), we need a method in Thread like, > > unsigned Thread::numberOfThreadGroups() > { > auto locker = holdLock(m_mutex); > return m_threadGroups.size(); > }
Thank you for your detailed advice! I'll try to make a test.
Takashi Komori
Comment 7
2019-08-06 00:02:47 PDT
Created
attachment 375610
[details]
Patch
Takashi Komori
Comment 8
2019-08-06 00:29:34 PDT
Created
attachment 375612
[details]
Patch
Yusuke Suzuki
Comment 9
2019-08-07 22:50:47 PDT
Comment on
attachment 375612
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=375612&action=review
Some early comments. The code looks good to me.
> Tools/TestWebKitAPI/Tests/WTF/ThreadGroup.cpp:156 > + const int NumberOfThreads = 64;
Use `unsigned` to avoid gtest build failure.
> Tools/TestWebKitAPI/Tests/WTF/ThreadGroup.cpp:162 > + Vector<RefPtr<Thread>> threads;
Use `Ref`.
> Tools/TestWebKitAPI/Tests/WTF/ThreadGroup.cpp:165 > + for (int i = 0; i < NumberOfThreads; i++) {
Use `unsigned`.
> Tools/TestWebKitAPI/Tests/WTF/ThreadGroup.cpp:166 > + auto thread = Thread::create("ThreadGroupWorker", [&](void) {
`(void)` is not necessary.
> Tools/TestWebKitAPI/Tests/WTF/ThreadGroup.cpp:167 > + LockHolder locker(lock);
Use `auto locker = holdLock(lock)`.
> Tools/TestWebKitAPI/Tests/WTF/ThreadGroup.cpp:168 > + threadRunningCondition.wait(lock, [&](void) {
`(void)` is not necessary.
> Tools/TestWebKitAPI/Tests/WTF/ThreadGroup.cpp:184 > + for (int i = 0; i < NumberOfThreads; i++)
Use `unsigned`.
Takashi Komori
Comment 10
2019-08-09 00:53:58 PDT
Created
attachment 375898
[details]
Patch
Takashi Komori
Comment 11
2019-08-09 01:52:48 PDT
Created
attachment 375899
[details]
Patch
Yusuke Suzuki
Comment 12
2019-08-09 02:53:01 PDT
Comment on
attachment 375899
[details]
Patch r=me
Darin Adler
Comment 13
2019-08-09 09:38:53 PDT
Comment on
attachment 375899
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=375899&action=review
> Source/WTF/wtf/Threading.h:296 > + HashMap<ThreadGroup*, std::weak_ptr<ThreadGroup>> m_threadGroupMap;
Future cleanup thought: Can we make HashSet<std::weak_ptr<ThreadGroup>> work for a case like this, rather than requiring use of a map?
Yusuke Suzuki
Comment 14
2019-08-09 10:41:03 PDT
Comment on
attachment 375899
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=375899&action=review
>> Source/WTF/wtf/Threading.h:296 >> + HashMap<ThreadGroup*, std::weak_ptr<ThreadGroup>> m_threadGroupMap; > > Future cleanup thought: Can we make HashSet<std::weak_ptr<ThreadGroup>> work for a case like this, rather than requiring use of a map?
Yeah, I would like to make this too :D Unfortunately, currently, `std::weak_ptr` does not have a way to get a raw pointer if the held object is dead (I would like to have `std::weak_ptr::get()`...). So we need our own WeakPtr implementation which is thread-safe and having a method (like WeakPtr::getRaw()) returning an original pointer regardless of liveness (thread-safe weak pointer is why we are using std::weak_ptr and std::shared_ptr instead of RefPtr and WeakPtr here).
WebKit Commit Bot
Comment 15
2019-08-12 20:01:17 PDT
Comment on
attachment 375899
[details]
Patch Clearing flags on attachment: 375899 Committed
r248586
: <
https://trac.webkit.org/changeset/248586
>
WebKit Commit Bot
Comment 16
2019-08-12 20:01:19 PDT
All reviewed patches have been landed. Closing bug.
Radar WebKit Bug Importer
Comment 17
2019-08-12 20:02:23 PDT
<
rdar://problem/54239165
>
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug