Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: dbus/exported_object.cc

Issue 8175009: Eliminate a timed wait from ExportedObject::HandleMessage(). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « dbus/exported_object.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "dbus/exported_object.h" 5 #include "dbus/exported_object.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/memory/ref_counted.h" 9 #include "base/memory/ref_counted.h"
10 #include "base/message_loop.h" 10 #include "base/message_loop.h"
(...skipping 21 matching lines...) Expand all
32 } 32 }
33 33
34 } // namespace 34 } // namespace
35 35
36 ExportedObject::ExportedObject(Bus* bus, 36 ExportedObject::ExportedObject(Bus* bus,
37 const std::string& service_name, 37 const std::string& service_name,
38 const std::string& object_path) 38 const std::string& object_path)
39 : bus_(bus), 39 : bus_(bus),
40 service_name_(service_name), 40 service_name_(service_name),
41 object_path_(object_path), 41 object_path_(object_path),
42 object_is_registered_(false), 42 object_is_registered_(false) {
43 response_from_method_(NULL),
44 on_method_is_called_(false /* manual_reset */,
45 false /* initially_signaled */) {
46 } 43 }
47 44
48 ExportedObject::~ExportedObject() { 45 ExportedObject::~ExportedObject() {
49 DCHECK(!object_is_registered_); 46 DCHECK(!object_is_registered_);
50 } 47 }
51 48
52 bool ExportedObject::ExportMethodAndBlock( 49 bool ExportedObject::ExportMethodAndBlock(
53 const std::string& interface_name, 50 const std::string& interface_name,
54 const std::string& method_name, 51 const std::string& method_name,
55 MethodCallCallback method_call_callback) { 52 MethodCallCallback method_call_callback) {
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 const std::string absolute_method_name = GetAbsoluteMethodName( 208 const std::string absolute_method_name = GetAbsoluteMethodName(
212 interface, member); 209 interface, member);
213 MethodTable::const_iterator iter = method_table_.find(absolute_method_name); 210 MethodTable::const_iterator iter = method_table_.find(absolute_method_name);
214 if (iter == method_table_.end()) { 211 if (iter == method_table_.end()) {
215 // Don't know about the method. 212 // Don't know about the method.
216 LOG(WARNING) << "Unknown method: " << method_call->ToString(); 213 LOG(WARNING) << "Unknown method: " << method_call->ToString();
217 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 214 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
218 } 215 }
219 216
220 const base::TimeTicks start_time = base::TimeTicks::Now(); 217 const base::TimeTicks start_time = base::TimeTicks::Now();
221 Response* response = NULL;
222 if (bus_->HasDBusThread()) { 218 if (bus_->HasDBusThread()) {
223 response_from_method_ = NULL;
224 // Post a task to run the method in the origin thread. 219 // Post a task to run the method in the origin thread.
225 bus_->PostTaskToOriginThread(FROM_HERE, 220 bus_->PostTaskToOriginThread(FROM_HERE,
226 base::Bind(&ExportedObject::RunMethod, 221 base::Bind(&ExportedObject::RunMethod,
227 this, 222 this,
228 iter->second, 223 iter->second,
229 method_call.get())); 224 method_call.release(),
230 // Wait until the method call is done. Blocking is not desirable but we 225 start_time));
231 // should return the response to the dbus-daemon in the function, so we
232 // don't have a choice. We wait in the D-Bus thread, so it should be ok.
233 {
234 // We need a timeout here in case the method gets stuck.
235 const int kTimeoutSecs = 10;
236 const base::TimeDelta timeout(
237 base::TimeDelta::FromSeconds(kTimeoutSecs));
238
239 const bool signaled = on_method_is_called_.TimedWait(timeout);
240 // Method not called is a fatal error. The method is likely stuck
241 // infinitely in the origin thread. No way to stop it from here.
242 CHECK(signaled) << "Method " << absolute_method_name << " not called";
243 }
244 response = response_from_method_;
245 } else { 226 } else {
246 // If the D-Bus thread is not used, just call the method directly. We 227 // If the D-Bus thread is not used, just call the method directly. We
247 // don't need the complicated logic to wait for the method call to be 228 // don't need the complicated logic to wait for the method call to be
248 // complete. 229 // complete.
249 response = iter->second.Run(method_call.get()); 230 // |response| will be deleted in OnMethodCompleted().
231 Response* response = iter->second.Run(method_call.get());
232 OnMethodCompleted(method_call.release(), response, start_time);
250 } 233 }
234
235 // It's valid to say HANDLED here, and send a method response at a later
236 // time from OnMethodCompleted() asynchronously.
237 return DBUS_HANDLER_RESULT_HANDLED;
238 }
239
240 void ExportedObject::RunMethod(MethodCallCallback method_call_callback,
241 MethodCall* method_call,
242 base::TimeTicks start_time) {
243 bus_->AssertOnOriginThread();
244
245 Response* response = method_call_callback.Run(method_call);
246 bus_->PostTaskToDBusThread(FROM_HERE,
247 base::Bind(&ExportedObject::OnMethodCompleted,
248 this,
249 method_call,
250 response,
251 start_time));
252 }
253
254 void ExportedObject::OnMethodCompleted(MethodCall* method_call,
255 Response* response,
256 base::TimeTicks start_time) {
257 bus_->AssertOnDBusThread();
258 scoped_ptr<MethodCall> method_call_deleter(method_call);
259 scoped_ptr<Response> response_deleter(response);
260
251 // Record if the method call is successful, or not. 1 if successful. 261 // Record if the method call is successful, or not. 1 if successful.
252 UMA_HISTOGRAM_ENUMERATION("DBus.ExportedMethodHandleSuccess", 262 UMA_HISTOGRAM_ENUMERATION("DBus.ExportedMethodHandleSuccess",
253 response ? 1 : 0, 263 response ? 1 : 0,
254 kSuccessRatioHistogramMaxValue); 264 kSuccessRatioHistogramMaxValue);
255 265
266 // Check if the bus is still connected. If the method takes long to
267 // complete, the bus may be shut down meanwhile.
268 if (!bus_->is_connected())
269 return;
270
256 if (!response) { 271 if (!response) {
257 // Something bad happened in the method call. 272 // Something bad happened in the method call.
258 scoped_ptr<dbus::ErrorResponse> error_response( 273 scoped_ptr<dbus::ErrorResponse> error_response(
259 ErrorResponse::FromMethodCall(method_call.get(), 274 ErrorResponse::FromMethodCall(
260 DBUS_ERROR_FAILED, 275 method_call,
261 "error occurred in " + member)); 276 DBUS_ERROR_FAILED,
262 dbus_connection_send(connection, error_response->raw_message(), NULL); 277 "error occurred in " + method_call->GetMember()));
263 return DBUS_HANDLER_RESULT_HANDLED; 278 bus_->Send(error_response->raw_message(), NULL);
279 return;
264 } 280 }
265 281
266 // The method call was successful. 282 // The method call was successful.
267 dbus_connection_send(connection, response->raw_message(), NULL); 283 bus_->Send(response->raw_message(), NULL);
268 delete response; 284
269 // Record time spent to handle the the method call. Don't include failures. 285 // Record time spent to handle the the method call. Don't include failures.
270 UMA_HISTOGRAM_TIMES("DBus.ExportedMethodHandleTime", 286 UMA_HISTOGRAM_TIMES("DBus.ExportedMethodHandleTime",
271 base::TimeTicks::Now() - start_time); 287 base::TimeTicks::Now() - start_time);
272
273 return DBUS_HANDLER_RESULT_HANDLED;
274 }
275
276 void ExportedObject::RunMethod(MethodCallCallback method_call_callback,
277 MethodCall* method_call) {
278 bus_->AssertOnOriginThread();
279
280 response_from_method_ = method_call_callback.Run(method_call);
281 on_method_is_called_.Signal();
282 } 288 }
283 289
284 void ExportedObject::OnUnregistered(DBusConnection* connection) { 290 void ExportedObject::OnUnregistered(DBusConnection* connection) {
285 } 291 }
286 292
287 DBusHandlerResult ExportedObject::HandleMessageThunk( 293 DBusHandlerResult ExportedObject::HandleMessageThunk(
288 DBusConnection* connection, 294 DBusConnection* connection,
289 DBusMessage* raw_message, 295 DBusMessage* raw_message,
290 void* user_data) { 296 void* user_data) {
291 ExportedObject* self = reinterpret_cast<ExportedObject*>(user_data); 297 ExportedObject* self = reinterpret_cast<ExportedObject*>(user_data);
292 return self->HandleMessage(connection, raw_message); 298 return self->HandleMessage(connection, raw_message);
293 } 299 }
294 300
295 void ExportedObject::OnUnregisteredThunk(DBusConnection *connection, 301 void ExportedObject::OnUnregisteredThunk(DBusConnection *connection,
296 void* user_data) { 302 void* user_data) {
297 ExportedObject* self = reinterpret_cast<ExportedObject*>(user_data); 303 ExportedObject* self = reinterpret_cast<ExportedObject*>(user_data);
298 return self->OnUnregistered(connection); 304 return self->OnUnregistered(connection);
299 } 305 }
300 306
301 } // namespace dbus 307 } // namespace dbus
OLDNEW
« no previous file with comments | « dbus/exported_object.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698