diff options
author | skyostil <skyostil@chromium.org> | 2016-01-07 04:15:45 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-01-07 12:16:45 +0000 |
commit | 3ae7dab6fb40b0fe1d5c18eda603a89a455394fd (patch) | |
tree | 942e7ec5dde567de9ac15b04c7a2d41625329dc8 /base | |
parent | fddbd80b03d2e2ac19fb1bdc2e26d8b4c856316b (diff) | |
download | chromium_src-3ae7dab6fb40b0fe1d5c18eda603a89a455394fd.zip chromium_src-3ae7dab6fb40b0fe1d5c18eda603a89a455394fd.tar.gz chromium_src-3ae7dab6fb40b0fe1d5c18eda603a89a455394fd.tar.bz2 |
base: Fix DCHECK when thread creation fails
When thread creation fails[1], base::Thread tries to delete an unbound
MessageLoop on the originating thread. If that thread already has a
MessageLoop, this trips a DCHECK in MessageLoop's destructor that checks
against having two MessageLoops on the same thread.
This patch adjusts the DCHECK logic to ignore destroying unbound message
loops on a thread that already has a separate message loop (which it was
already trying to do according to the comments).
[1] https://code.google.com/p/chromium/codesearch#chromium/src/base/threading/thread.cc&l=116
BUG=480100
Review URL: https://codereview.chromium.org/1559353002
Cr-Commit-Position: refs/heads/master@{#368057}
Diffstat (limited to 'base')
-rw-r--r-- | base/message_loop/message_loop.cc | 11 | ||||
-rw-r--r-- | base/message_loop/message_loop.h | 2 | ||||
-rw-r--r-- | base/message_loop/message_loop_unittest.cc | 11 |
3 files changed, 20 insertions, 4 deletions
diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc index cfa86d9..13bc854 100644 --- a/base/message_loop/message_loop.cc +++ b/base/message_loop/message_loop.cc @@ -133,9 +133,11 @@ MessageLoop::MessageLoop(scoped_ptr<MessagePump> pump) } MessageLoop::~MessageLoop() { - // current() could be NULL if this message loop is destructed before it is - // bound to a thread. - DCHECK(current() == this || !current()); + // If |pump_| is non-null, this message loop has been bound and should be the + // current one on this thread. Otherwise, this loop is being destructed before + // it was bound to a thread, so a different message loop (or no loop at all) + // may be current. + DCHECK((pump_ && current() == this) || (!pump_ && current() != this)); // iOS just attaches to the loop, it doesn't Run it. // TODO(stuartmorgan): Consider wiring up a Detach(). @@ -177,7 +179,8 @@ MessageLoop::~MessageLoop() { task_runner_ = NULL; // OK, now make it so that no one can find us. - lazy_tls_ptr.Pointer()->Set(NULL); + if (current() == this) + lazy_tls_ptr.Pointer()->Set(nullptr); } // static diff --git a/base/message_loop/message_loop.h b/base/message_loop/message_loop.h index 364d04d..8ef8d6a 100644 --- a/base/message_loop/message_loop.h +++ b/base/message_loop/message_loop.h @@ -11,6 +11,7 @@ #include "base/base_export.h" #include "base/callback_forward.h" #include "base/debug/task_annotator.h" +#include "base/gtest_prod_util.h" #include "base/location.h" #include "base/macros.h" #include "base/memory/ref_counted.h" @@ -403,6 +404,7 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate { friend class internal::IncomingTaskQueue; friend class ScheduleWorkTest; friend class Thread; + FRIEND_TEST_ALL_PREFIXES(MessageLoopTest, DeleteUnboundLoop); using MessagePumpFactoryCallback = Callback<scoped_ptr<MessagePump>()>; diff --git a/base/message_loop/message_loop_unittest.cc b/base/message_loop/message_loop_unittest.cc index 8b7a84d..1a3a925 100644 --- a/base/message_loop/message_loop_unittest.cc +++ b/base/message_loop/message_loop_unittest.cc @@ -1041,4 +1041,15 @@ TEST(MessageLoopTest, OriginalRunnerWorks) { EXPECT_EQ(1, foo->test_count()); } +TEST(MessageLoopTest, DeleteUnboundLoop) { + // It should be possible to delete an unbound message loop on a thread which + // already has another active loop. This happens when thread creation fails. + MessageLoop loop; + scoped_ptr<MessageLoop> unbound_loop(MessageLoop::CreateUnbound( + MessageLoop::TYPE_DEFAULT, MessageLoop::MessagePumpFactoryCallback())); + unbound_loop.reset(); + EXPECT_EQ(&loop, MessageLoop::current()); + EXPECT_EQ(loop.task_runner(), ThreadTaskRunnerHandle::Get()); +} + } // namespace base |