From 24d5cc6bb1328948d7a0658a7fa3acf6de5b91f8 Mon Sep 17 00:00:00 2001
From: "sergeyu@chromium.org"
 <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>
Date: Thu, 23 Dec 2010 23:40:30 +0000
Subject: [PATCH] Fix crash in JingleThread caused by non-nestable tasks.

BUG=None
TEST=Unittests

Review URL: http://codereview.chromium.org/6003003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@70115 0039d316-1c4b-4281-b951-d872f2087c98
---
 remoting/jingle_glue/jingle_thread.cc         | 18 ++++++++-----
 .../jingle_glue/jingle_thread_unittest.cc     | 26 +++++++++++++++++++
 2 files changed, 37 insertions(+), 7 deletions(-)

diff --git a/remoting/jingle_glue/jingle_thread.cc b/remoting/jingle_glue/jingle_thread.cc
index 25f646a1510cf..b8bc42874a851 100644
--- a/remoting/jingle_glue/jingle_thread.cc
+++ b/remoting/jingle_glue/jingle_thread.cc
@@ -42,12 +42,6 @@ class JingleThread::JingleMessagePump : public base::MessagePump,
     // TODO(sergeyu): Remove it when JingleThread moved on Chromium's
     // base::Thread.
     base::MessagePump::Delegate* delegate = thread_->message_loop();
-    // Loop until we run out of work.
-    while (true) {
-      if (!delegate->DoWork())
-        break;
-    }
-
     // Process all pending tasks.
     while (true) {
       if (delegate->DoWork())
@@ -61,7 +55,6 @@ class JingleThread::JingleMessagePump : public base::MessagePump,
   }
 
  private:
-
   void ScheduleNextDelayedTask() {
     DCHECK_EQ(thread_->message_loop(), MessageLoop::current());
 
@@ -86,6 +79,16 @@ class JingleThread::JingleMessageLoop : public MessageLoop {
       : MessageLoop(MessageLoop::TYPE_IO) {
     pump_ = new JingleMessagePump(thread);
   }
+
+  void Initialize() {
+    jingle_message_loop_state_.reset(new AutoRunState(this));
+  }
+
+ private:
+  // AutoRunState sets |state_| for this message loop. It needs to be
+  // created here because we never call Run() or RunAllPending() for
+  // the thread.
+  scoped_ptr<AutoRunState> jingle_message_loop_state_;
 };
 
 TaskPump::TaskPump() {
@@ -119,6 +122,7 @@ void JingleThread::Start() {
 
 void JingleThread::Run() {
   JingleMessageLoop message_loop(this);
+  message_loop.Initialize();
   message_loop_ = &message_loop;
 
   TaskPump task_pump;
diff --git a/remoting/jingle_glue/jingle_thread_unittest.cc b/remoting/jingle_glue/jingle_thread_unittest.cc
index bbaad799ee0ae..e1447275f1099 100644
--- a/remoting/jingle_glue/jingle_thread_unittest.cc
+++ b/remoting/jingle_glue/jingle_thread_unittest.cc
@@ -33,6 +33,16 @@ TEST(JingleThreadTest, PostTask) {
   thread.Stop();
 }
 
+TEST(JingleThreadTest, PostNonNestableTask) {
+  JingleThread thread;
+  MockTask* task = new MockTask();
+  EXPECT_CALL(*task, Run());
+
+  thread.Start();
+  thread.message_loop()->PostNonNestableTask(FROM_HERE, task);
+  thread.Stop();
+}
+
 ACTION_P(SignalEvent, event) {
   event->Signal();
 }
@@ -53,4 +63,20 @@ TEST(JingleThreadTest, PostDelayedTask) {
   EXPECT_GE((end - start).InMillisecondsRoundedUp(), kDelayMs);
 }
 
+TEST(JingleThreadTest, PostNonNestableDelayedTask) {
+  JingleThread thread;
+  MockTask* task = new MockTask();
+  base::WaitableEvent event(true, false);
+  EXPECT_CALL(*task, Run()).WillOnce(SignalEvent(&event));
+
+  thread.Start();
+  base::Time start = base::Time::Now();
+  thread.message_loop()->PostNonNestableDelayedTask(FROM_HERE, task, kDelayMs);
+  event.TimedWait(base::TimeDelta::FromMilliseconds(kDelayTimeoutMs));
+  base::Time end = base::Time::Now();
+  thread.Stop();
+
+  EXPECT_GE((end - start).InMillisecondsRoundedUp(), kDelayMs);
+}
+
 }  // namespace remoting
-- 
GitLab