Files
sdk/runtime/vm/message_test.cc
T
turnidge@google.com c658fa60f9 Fix deadlock that can occur while handling service messages at a breakpoint.
Deadlock looks like:

  Regular Isolate
  -> paused at breakpoint in debug message loop
  -> holds debug message queue lock to get message notifications
  -> handles an service message
  -> waits for portmap lock to send response

  Service Isolate
  -> receives request for paused isolate
  -> holds portmap lock to send message
  -> runs custom message notifier to wake debug message loop
  -> waits for debug message queue lock

I've solved this by releasing the debug message queue lock while
handling service messages.  This requires me to poll for new service
messages after reacquiring the debug message queue lock to make sure I
haven't dropped any notifications.

It's a little weird that the embedder (runtime/bin) needs to be aware
of the locking in the core vm (runtime/vm), but this seemed like the
simplest fix for now.

BUG=
R=johnmccutchan@google.com

Review URL: https://codereview.chromium.org//629533002

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@41326 260f80e4-7a28-3924-810f-c04153c831b5
2014-10-27 16:57:21 +00:00

82 lines
1.9 KiB
C++

// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "platform/assert.h"
#include "vm/message.h"
#include "vm/unit_test.h"
namespace dart {
static uint8_t* AllocMsg(const char* str) {
return reinterpret_cast<uint8_t*>(strdup(str));
}
TEST_CASE(MessageQueue_BasicOperations) {
MessageQueue queue;
EXPECT(queue.IsEmpty());
Dart_Port port = 1;
const char* str1 = "msg1";
const char* str2 = "msg2";
// Add two messages.
Message* msg1 =
new Message(port, AllocMsg(str1), strlen(str1) + 1,
Message::kNormalPriority);
queue.Enqueue(msg1);
EXPECT(!queue.IsEmpty());
Message* msg2 =
new Message(port, AllocMsg(str2), strlen(str2) + 1,
Message::kNormalPriority);
queue.Enqueue(msg2);
EXPECT(!queue.IsEmpty());
// Remove two messages.
Message* msg = queue.Dequeue();
EXPECT(msg != NULL);
EXPECT_STREQ(str1, reinterpret_cast<char*>(msg->data()));
EXPECT(!queue.IsEmpty());
msg = queue.Dequeue();
EXPECT(msg != NULL);
EXPECT_STREQ(str2, reinterpret_cast<char*>(msg->data()));
EXPECT(queue.IsEmpty());
delete msg1;
delete msg2;
}
TEST_CASE(MessageQueue_Clear) {
MessageQueue queue;
Dart_Port port1 = 1;
Dart_Port port2 = 2;
const char* str1 = "msg1";
const char* str2 = "msg2";
// Add two messages.
Message* msg1 =
new Message(port1, AllocMsg(str1), strlen(str1) + 1,
Message::kNormalPriority);
queue.Enqueue(msg1);
Message* msg2 =
new Message(port2, AllocMsg(str2), strlen(str2) + 1,
Message::kNormalPriority);
queue.Enqueue(msg2);
EXPECT(!queue.IsEmpty());
queue.Clear();
EXPECT(queue.IsEmpty());
// msg1 and msg2 already delete by FlushAll.
}
} // namespace dart