0

dbus: No infinite timeout calls on ChromeOS system daemon

ChromeOS system daemon will be configured to have a max reply
timeout (of 1 hour). Replace `TIMEOUT_INFINITE` in existing
calls with `TIMEOUT_MAX_CHROMEOS` for ChromeOS.

Bug: b:388332345
Change-Id: Ic664ab3047cd396911202e8da6cfd613ce4499a4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6261306
Reviewed-by: Ryo Hashimoto <hashimoto@chromium.org>
Reviewed-by: David Padlipsky <dpad@google.com>
Commit-Queue: Xiyuan Xia <xiyuan@chromium.org>
Reviewed-by: Michael Sun <michaelfsun@google.com>
Reviewed-by: Nina Satragno <nsatragno@chromium.org>
Reviewed-by: Igor <igorcov@chromium.org>
Reviewed-by: Achuith Bhandarkar <achuith@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1422528}
This commit is contained in:
Xiyuan Xia
2025-02-20 07:03:04 -08:00
committed by Chromium LUCI CQ
parent 1fac544ef2
commit 2e2f97adb3
6 changed files with 49 additions and 28 deletions
chromeos
ash
components
dbus
dbus
device/bluetooth/dbus

@@ -256,9 +256,10 @@ class FwupdClientImpl : public FwupdClient {
writer.CloseContainer(&array_writer); writer.CloseContainer(&array_writer);
// TODO(michaelcheco): Investigate whether or not the estimated install time // TODO(michaelcheco): Investigate whether or not the estimated install time
// multiplied by some factor can be used in place of |TIMEOUT_INFINITE|. // multiplied by some factor can be used in place of
// `TIMEOUT_MAX`.
proxy_->CallMethodWithErrorResponse( proxy_->CallMethodWithErrorResponse(
&method_call, dbus::ObjectProxy::TIMEOUT_INFINITE, &method_call, dbus::ObjectProxy::TIMEOUT_MAX,
base::BindOnce(&FwupdClientImpl::InstallUpdateCallback, base::BindOnce(&FwupdClientImpl::InstallUpdateCallback,
weak_ptr_factory_.GetWeakPtr(), std::move(callback))); weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
} }

@@ -580,14 +580,10 @@ class SessionManagerClientImpl : public SessionManagerClient {
login_manager::kSessionManagerInterface, login_manager::kSessionManagerInterface,
login_manager::kSessionManagerGetServerBackedStateKeys); login_manager::kSessionManagerGetServerBackedStateKeys);
// Infinite timeout needed because the state keys are not generated as long // Long timeout needed because the state keys are not generated as long
// as the time sync hasn't been done (which requires network). // as the time sync hasn't been done (which requires network).
// TODO(igorcov): Since this is a resource allocated that could last a long
// time, we will need to change the behavior to either listen to
// LastSyncInfo event from tlsdated or communicate through signals with
// session manager in this particular flow.
session_manager_proxy_->CallMethodWithErrorResponse( session_manager_proxy_->CallMethodWithErrorResponse(
&method_call, dbus::ObjectProxy::TIMEOUT_INFINITE, &method_call, dbus::ObjectProxy::TIMEOUT_MAX,
base::BindOnce(&SessionManagerClientImpl::OnGetServerBackedStateKeys, base::BindOnce(&SessionManagerClientImpl::OnGetServerBackedStateKeys,
weak_ptr_factory_.GetWeakPtr(), std::move(callback))); weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
} }

@@ -35,9 +35,16 @@ constexpr char kGetAssertionStatusHistogram[] =
// Some methods trigger an OS modal dialog that needs to be completed or // Some methods trigger an OS modal dialog that needs to be completed or
// dismissed before the method returns. These methods are cancelled explicitly // dismissed before the method returns. These methods are cancelled explicitly
// once original WebAuthn request times out. Hence, they are invoked with // once original WebAuthn request times out.
// infinite DBus timeouts. //
const int kU2FInfiniteTimeout = dbus::ObjectProxy::TIMEOUT_INFINITE; // W3C spec recommends 5 min timeout:
// https://w3c.github.io/webauthn/#sctn-timeout-recommended-range
//
// Chrome since M120 can support up to 20 hours:
// https://lists.w3.org/Archives/Public/public-webauthn/2023Oct/0151.html
//
// In practice, `TIMEOUT_MAX` (1 hour) should be long enough.
const int kU2FMaxTimeout = dbus::ObjectProxy::TIMEOUT_MAX;
// Timeout for methods which don't take time proportional to the number of total // Timeout for methods which don't take time proportional to the number of total
// credentials. // credentials.
@@ -165,7 +172,7 @@ void U2FClientImpl::MakeCredential(
dbus::MessageWriter writer(&method_call); dbus::MessageWriter writer(&method_call);
writer.AppendProtoAsArrayOfBytes(request); writer.AppendProtoAsArrayOfBytes(request);
proxy_->CallMethod( proxy_->CallMethod(
&method_call, kU2FInfiniteTimeout, &method_call, kU2FMaxTimeout,
base::BindOnce( base::BindOnce(
[](DBusMethodCallback<u2f::MakeCredentialResponse> callback, [](DBusMethodCallback<u2f::MakeCredentialResponse> callback,
dbus::Response* dbus_response) { dbus::Response* dbus_response) {
@@ -203,7 +210,7 @@ void U2FClientImpl::GetAssertion(
}, },
std::move(callback)); std::move(callback));
proxy_->CallMethod( proxy_->CallMethod(
&method_call, kU2FInfiniteTimeout, &method_call, kU2FMaxTimeout,
base::BindOnce(&U2FClientImpl::HandleResponse<u2f::GetAssertionResponse>, base::BindOnce(&U2FClientImpl::HandleResponse<u2f::GetAssertionResponse>,
weak_factory_.GetWeakPtr(), weak_factory_.GetWeakPtr(),
std::move(uma_callback_wrapper))); std::move(uma_callback_wrapper)));

@@ -5,8 +5,10 @@
#include "dbus/object_proxy.h" #include "dbus/object_proxy.h"
#include <stddef.h> #include <stddef.h>
#include <utility> #include <utility>
#include "base/check.h"
#include "base/containers/contains.h" #include "base/containers/contains.h"
#include "base/debug/alias.h" #include "base/debug/alias.h"
#include "base/debug/leak_annotations.h" #include "base/debug/leak_annotations.h"
@@ -18,6 +20,7 @@
#include "base/threading/scoped_blocking_call.h" #include "base/threading/scoped_blocking_call.h"
#include "base/threading/thread.h" #include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h" #include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "dbus/bus.h" #include "dbus/bus.h"
#include "dbus/dbus_statistics.h" #include "dbus/dbus_statistics.h"
#include "dbus/error.h" #include "dbus/error.h"
@@ -132,6 +135,11 @@ base::expected<std::unique_ptr<Response>, Error>
ObjectProxy::CallMethodAndBlock(MethodCall* method_call, int timeout_ms) { ObjectProxy::CallMethodAndBlock(MethodCall* method_call, int timeout_ms) {
bus_->AssertOnDBusThread(); bus_->AssertOnDBusThread();
#if BUILDFLAG(IS_CHROMEOS)
// ChromeOS system daemon has `reply_timeout` configured.
CHECK_LE(timeout_ms, TIMEOUT_MAX);
#endif // BUILDFLAG(IS_CHROMEOS)
if (!bus_->Connect() || !method_call->SetDestination(service_name_) || if (!bus_->Connect() || !method_call->SetDestination(service_name_) ||
!method_call->SetPath(object_path_)) { !method_call->SetPath(object_path_)) {
// Not an error from libdbus, so returns invalid error. // Not an error from libdbus, so returns invalid error.
@@ -167,6 +175,11 @@ void ObjectProxy::CallMethodWithErrorResponse(
ResponseOrErrorCallback callback) { ResponseOrErrorCallback callback) {
bus_->AssertOnOriginThread(); bus_->AssertOnOriginThread();
#if BUILDFLAG(IS_CHROMEOS)
// ChromeOS system daemon has `reply_timeout` configured.
CHECK_LE(timeout_ms, TIMEOUT_MAX);
#endif // BUILDFLAG(IS_CHROMEOS)
ReplyCallbackHolder callback_holder(bus_->GetOriginTaskRunner(), ReplyCallbackHolder callback_holder(bus_->GetOriginTaskRunner(),
std::move(callback)); std::move(callback));

@@ -62,13 +62,16 @@ class CHROME_DBUS_EXPORT ObjectProxy
}; };
// Special timeout constants. // Special timeout constants.
//
// The constants correspond to DBUS_TIMEOUT_USE_DEFAULT and
// DBUS_TIMEOUT_INFINITE. Here we use literal numbers instead of these
// macros as these aren't defined with D-Bus earlier than 1.4.12.
enum { enum {
// The constant corresponds to DBUS_TIMEOUT_USE_DEFAULT. Here we use literal
// numbers instead of these macros as these aren't defined with D-Bus
// earlier than 1.4.12.
TIMEOUT_USE_DEFAULT = -1, TIMEOUT_USE_DEFAULT = -1,
TIMEOUT_INFINITE = 0x7fffffff,
// Max timeout for methods calls. Long method calls add to `pending_replies"
// in dbus_daemon and it has a limit. Once that limit is exceeded, no more
// calls could be made on the relevant DBusConnection.
TIMEOUT_MAX = base::Hours(1).InMilliseconds(),
}; };
// Called when an error response is returned or no response is returned. // Called when an error response is returned or no response is returned.

@@ -302,9 +302,9 @@ class BluetoothDeviceClientImpl : public BluetoothDeviceClient,
return; return;
} }
// Connect may take an arbitrary length of time, so use no timeout. // Connect may take an arbitrary length of time, so use the max timeout.
object_proxy->CallMethodWithErrorCallback( object_proxy->CallMethodWithErrorCallback(
&method_call, dbus::ObjectProxy::TIMEOUT_INFINITE, &method_call, dbus::ObjectProxy::TIMEOUT_MAX,
base::BindOnce(&BluetoothDeviceClientImpl::OnSuccess, base::BindOnce(&BluetoothDeviceClientImpl::OnSuccess,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)), weak_ptr_factory_.GetWeakPtr(), std::move(callback)),
base::BindOnce(&BluetoothDeviceClientImpl::OnError, base::BindOnce(&BluetoothDeviceClientImpl::OnError,
@@ -326,9 +326,10 @@ class BluetoothDeviceClientImpl : public BluetoothDeviceClient,
return; return;
} }
// ConnectClassic may take an arbitrary length of time, so use no timeout. // ConnectClassic may take an arbitrary length of time, so use the max
// timeout.
object_proxy->CallMethodWithErrorCallback( object_proxy->CallMethodWithErrorCallback(
&method_call, dbus::ObjectProxy::TIMEOUT_INFINITE, &method_call, dbus::ObjectProxy::TIMEOUT_MAX,
base::BindOnce(&BluetoothDeviceClientImpl::OnSuccess, base::BindOnce(&BluetoothDeviceClientImpl::OnSuccess,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)), weak_ptr_factory_.GetWeakPtr(), std::move(callback)),
base::BindOnce(&BluetoothDeviceClientImpl::OnError, base::BindOnce(&BluetoothDeviceClientImpl::OnError,
@@ -350,9 +351,9 @@ class BluetoothDeviceClientImpl : public BluetoothDeviceClient,
return; return;
} }
// ConnectLE may take an arbitrary length of time, so use no timeout. // ConnectLE may take an arbitrary length of time, so use the max timeout.
object_proxy->CallMethodWithErrorCallback( object_proxy->CallMethodWithErrorCallback(
&method_call, dbus::ObjectProxy::TIMEOUT_INFINITE, &method_call, dbus::ObjectProxy::TIMEOUT_MAX,
base::BindOnce(&BluetoothDeviceClientImpl::OnSuccess, base::BindOnce(&BluetoothDeviceClientImpl::OnSuccess,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)), weak_ptr_factory_.GetWeakPtr(), std::move(callback)),
base::BindOnce(&BluetoothDeviceClientImpl::OnError, base::BindOnce(&BluetoothDeviceClientImpl::OnError,
@@ -424,9 +425,9 @@ class BluetoothDeviceClientImpl : public BluetoothDeviceClient,
return; return;
} }
// Connect may take an arbitrary length of time, so use no timeout. // Connect may take an arbitrary length of time, so use the max timeout.
object_proxy->CallMethodWithErrorCallback( object_proxy->CallMethodWithErrorCallback(
&method_call, dbus::ObjectProxy::TIMEOUT_INFINITE, &method_call, dbus::ObjectProxy::TIMEOUT_MAX,
base::BindOnce(&BluetoothDeviceClientImpl::OnSuccess, base::BindOnce(&BluetoothDeviceClientImpl::OnSuccess,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)), weak_ptr_factory_.GetWeakPtr(), std::move(callback)),
base::BindOnce(&BluetoothDeviceClientImpl::OnError, base::BindOnce(&BluetoothDeviceClientImpl::OnError,
@@ -476,9 +477,9 @@ class BluetoothDeviceClientImpl : public BluetoothDeviceClient,
return; return;
} }
// Pairing may take an arbitrary length of time, so use no timeout. // Pairing may take an arbitrary length of time, so use the max timeout.
object_proxy->CallMethodWithErrorCallback( object_proxy->CallMethodWithErrorCallback(
&method_call, dbus::ObjectProxy::TIMEOUT_INFINITE, &method_call, dbus::ObjectProxy::TIMEOUT_MAX,
base::BindOnce(&BluetoothDeviceClientImpl::OnSuccess, base::BindOnce(&BluetoothDeviceClientImpl::OnSuccess,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)), weak_ptr_factory_.GetWeakPtr(), std::move(callback)),
base::BindOnce(&BluetoothDeviceClientImpl::OnError, base::BindOnce(&BluetoothDeviceClientImpl::OnError,