summaryrefslogtreecommitdiffstats
path: root/dbus
diff options
context:
space:
mode:
Diffstat (limited to 'dbus')
-rw-r--r--dbus/end_to_end_async_unittest.cc35
-rw-r--r--dbus/object_proxy.cc35
2 files changed, 69 insertions, 1 deletions
diff --git a/dbus/end_to_end_async_unittest.cc b/dbus/end_to_end_async_unittest.cc
index d5e278f..7715f7d 100644
--- a/dbus/end_to_end_async_unittest.cc
+++ b/dbus/end_to_end_async_unittest.cc
@@ -20,6 +20,14 @@
#include "dbus/test_service.h"
#include "testing/gtest/include/gtest/gtest.h"
+namespace {
+
+// See comments in ObjectProxy::RunResponseCallback() for why the number was
+// chosen.
+const int kHugePayloadSize = 64 << 20; // 64 MB
+
+} // namespace
+
// The end-to-end test exercises the asynchronous APIs in ObjectProxy and
// ExportedObject.
class EndToEndAsyncTest : public testing::Test {
@@ -313,6 +321,23 @@ TEST_F(EndToEndAsyncTest, EchoThreeTimes) {
EXPECT_EQ("foo", response_strings_[2]);
}
+TEST_F(EndToEndAsyncTest, Echo_HugePayload) {
+ const std::string kHugePayload(kHugePayloadSize, 'o');
+
+ // Create the method call with a huge payload.
+ dbus::MethodCall method_call("org.chromium.TestInterface", "Echo");
+ dbus::MessageWriter writer(&method_call);
+ writer.AppendString(kHugePayload);
+
+ // Call the method.
+ const int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT;
+ CallMethod(&method_call, timeout_ms);
+
+ // This caused a DCHECK failure before. Ensure that the issue is fixed.
+ WaitForResponses(1);
+ EXPECT_EQ(kHugePayload, response_strings_[0]);
+}
+
TEST_F(EndToEndAsyncTest, BrokenBus) {
const char* kHello = "hello";
@@ -537,6 +562,16 @@ TEST_F(EndToEndAsyncTest, TestSignalFromRoot) {
ASSERT_EQ(kMessage, root_test_signal_string_);
}
+TEST_F(EndToEndAsyncTest, TestHugeSignal) {
+ const std::string kHugeMessage(kHugePayloadSize, 'o');
+
+ // Send the huge signal from the exported object.
+ test_service_->SendTestSignal(kHugeMessage);
+ // This caused a DCHECK failure before. Ensure that the issue is fixed.
+ WaitForTestSignal();
+ ASSERT_EQ(kHugeMessage, test_signal_string_);
+}
+
class SignalReplacementTest : public EndToEndAsyncTest {
public:
SignalReplacementTest() {
diff --git a/dbus/object_proxy.cc b/dbus/object_proxy.cc
index ea5f330..62c0eb8 100644
--- a/dbus/object_proxy.cc
+++ b/dbus/object_proxy.cc
@@ -277,12 +277,40 @@ void ObjectProxy::RunResponseCallback(ResponseCallback response_callback,
scoped_ptr<dbus::ErrorResponse> error_response(
dbus::ErrorResponse::FromRawMessage(response_message));
error_callback.Run(error_response.get());
+ // Delete the message on the D-Bus thread. See below for why.
+ bus_->PostTaskToDBusThread(
+ FROM_HERE,
+ base::Bind(&base::DeletePointer<dbus::ErrorResponse>,
+ error_response.release()));
} else {
// This will take |response_message| and release (unref) it.
scoped_ptr<dbus::Response> response(
dbus::Response::FromRawMessage(response_message));
// The response is successfully received.
response_callback.Run(response.get());
+ // The message should be deleted on the D-Bus thread for a complicated
+ // reason:
+ //
+ // libdbus keeps track of the number of bytes in the incoming message
+ // queue to ensure that the data size in the queue is manageable. The
+ // bookkeeping is partly done via dbus_message_unref(), and immediately
+ // asks the client code (Chrome) to stop monitoring the underlying
+ // socket, if the number of bytes exceeds a certian number, which is set
+ // to 63MB, per dbus-transport.cc:
+ //
+ // /* Try to default to something that won't totally hose the system,
+ // * but doesn't impose too much of a limitation.
+ // */
+ // transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63;
+ //
+ // The monitoring of the socket is done on the D-Bus thread (see Watch
+ // class in bus.cc), hence we should stop the monitoring from D-Bus
+ // thread, not from the current thread here, which is likely UI thread.
+ bus_->PostTaskToDBusThread(
+ FROM_HERE,
+ base::Bind(&base::DeletePointer<dbus::Response>,
+ response.release()));
+
method_call_successful = true;
// Record time spent for the method call. Don't include failures.
UMA_HISTOGRAM_TIMES("DBus.AsyncMethodCallTime",
@@ -438,7 +466,12 @@ void ObjectProxy::RunMethod(base::TimeTicks start_time,
bus_->AssertOnOriginThread();
signal_callback.Run(signal);
- delete signal;
+ // Delete the message on the D-Bus thread. See comments in
+ // RunResponseCallback().
+ bus_->PostTaskToDBusThread(
+ FROM_HERE,
+ base::Bind(&base::DeletePointer<dbus::Signal>, signal));
+
// Record time spent for handling the signal.
UMA_HISTOGRAM_TIMES("DBus.SignalHandleTime",
base::TimeTicks::Now() - start_time);