From 38fec84afea21b4d65f2df292c773e6579419d79 Mon Sep 17 00:00:00 2001 From: Marek Maslanka Date: Tue, 5 Mar 2024 09:47:51 +0000 Subject: [PATCH] Add a limit for pending messages to a single service Allows to define the maximum number of pending messages for a single destination service. It extends the existing functionality of checking the number of pending messages from the sender in the message queue. By setting the maximum number of pending messages for a single service can prevent reaching the limit of messages sent by service in case when one of the destination services doesn't respond within the timeout limit, thus preventing the next messages from the sender from being skipped. Signed-off-by: Marek Maslanka --- bus/bus.c | 6 ++++ bus/bus.h | 3 ++ bus/config-parser.c | 13 +++++++++ bus/connection.c | 29 ++++++++++++++++--- bus/session.conf.in | 1 + bus/system.conf.in | 1 + doc/dbus-daemon.1.xml.in | 3 ++ .../tmp-session-like-system.conf.in | 1 + .../valid-config-files/incoming-limit.conf.in | 1 + .../max-replies-per-connection.conf.in | 2 ++ .../valid-config-files/tmp-session.conf.in | 1 + 11 files changed, 57 insertions(+), 4 deletions(-) diff --git a/bus/bus.c b/bus/bus.c index 62d58f8e..cf251234 100644 --- a/bus/bus.c +++ b/bus/bus.c @@ -1513,6 +1513,12 @@ bus_context_get_max_replies_per_connection (BusContext *context) return context->limits.max_replies_per_connection; } +int +bus_context_get_max_messages_for_service_per_connection (BusContext *context) +{ + return context->limits.max_messages_for_service_per_connection; +} + int bus_context_get_reply_timeout (BusContext *context) { diff --git a/bus/bus.h b/bus/bus.h index 88451ebb..6ca0a1fe 100644 --- a/bus/bus.h +++ b/bus/bus.h @@ -67,6 +67,7 @@ typedef struct int max_services_per_connection; /**< Max number of owned services for a single connection */ int max_match_rules_per_connection; /**< Max number of match rules for a single connection */ int max_replies_per_connection; /**< Max number of replies that can be pending for each connection */ + int max_messages_for_service_per_connection; /**< Max number of messages that can be pending for a single service per connection */ int reply_timeout; /**< How long to wait before timing out a reply */ int max_containers; /**< Max number of restricted servers for app-containers */ int max_containers_per_user; /**< Max number of restricted servers for app-containers, per user */ @@ -129,6 +130,8 @@ int bus_context_get_max_pending_activations (BusContext int bus_context_get_max_services_per_connection (BusContext *context); int bus_context_get_max_match_rules_per_connection (BusContext *context); int bus_context_get_max_replies_per_connection (BusContext *context); +int bus_context_get_max_messages_for_service_per_connection + (BusContext *context); int bus_context_get_reply_timeout (BusContext *context); int bus_context_get_max_containers (BusContext *context); int bus_context_get_max_containers_per_user (BusContext *context); diff --git a/bus/config-parser.c b/bus/config-parser.c index de9a1398..f888a46f 100644 --- a/bus/config-parser.c +++ b/bus/config-parser.c @@ -554,6 +554,12 @@ bus_config_parser_new (const DBusString *basedir, * that require a reply */ parser->limits.max_replies_per_connection = 128; + + /* Limit the maximum number of pending messages for a single service + * per connection. The default is half the pending replies limit for + * the connection. + */ + parser->limits.max_messages_for_service_per_connection = 64; } parser->refcount = 1; @@ -2171,6 +2177,12 @@ set_limit (BusConfigParser *parser, must_be_int = TRUE; parser->limits.max_replies_per_connection = value; } + else if (strcmp (name, "max_messages_for_service_per_connection") == 0) + { + must_be_positive = TRUE; + must_be_int = TRUE; + parser->limits.max_messages_for_service_per_connection = value; + } else if (strcmp (name, "max_containers") == 0) { must_be_positive = TRUE; @@ -3478,6 +3490,7 @@ limits_equal (const BusLimits *a, && a->max_services_per_connection == b->max_services_per_connection && a->max_match_rules_per_connection == b->max_match_rules_per_connection && a->max_replies_per_connection == b->max_replies_per_connection + && a->max_messages_for_service_per_connection == b->max_messages_for_service_per_connection && a->reply_timeout == b->reply_timeout); } diff --git a/bus/connection.c b/bus/connection.c index f0177c6f..41e09f66 100644 --- a/bus/connection.c +++ b/bus/connection.c @@ -1960,7 +1960,8 @@ bus_connections_expect_reply (BusConnections *connections, dbus_uint32_t reply_serial; DBusList *link; CancelPendingReplyData *cprd; - int count; + int wait_for_replies_count; + int service_outgoing_msg_count; int limit; _dbus_assert (will_get_reply != NULL); @@ -1973,7 +1974,8 @@ bus_connections_expect_reply (BusConnections *connections, reply_serial = dbus_message_get_serial (reply_to_this); link = bus_expire_list_get_first_link (connections->pending_replies); - count = 0; + wait_for_replies_count = 0; + service_outgoing_msg_count = 0; while (link != NULL) { pending = link->data; @@ -1990,12 +1992,31 @@ bus_connections_expect_reply (BusConnections *connections, link = bus_expire_list_get_next_link (connections->pending_replies, link); if (pending->will_get_reply == will_get_reply) - ++count; + ++wait_for_replies_count; + if (pending->will_send_reply == will_send_reply) + ++service_outgoing_msg_count; } + limit = bus_context_get_max_messages_for_service_per_connection (connections->context); + + if (service_outgoing_msg_count >= limit) + { + bus_context_log (connections->context, DBUS_SYSTEM_LOG_WARNING, + "the maximum number of pending messages for " + "\"%s\" (%s) has been reached " + "(max_messages_for_service_per_connection=%d)", + bus_connection_get_name (will_send_reply), + bus_connection_get_loginfo (will_send_reply), + limit); + + dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED, + "the maximum number of pending messages for service per connection has been reached"); + return FALSE; + } + limit = bus_context_get_max_replies_per_connection (connections->context); - if (count >= limit) + if (wait_for_replies_count >= limit) { bus_context_log (connections->context, DBUS_SYSTEM_LOG_WARNING, "The maximum number of pending replies for " diff --git a/bus/session.conf.in b/bus/session.conf.in index affa7f1d..6b2531fd 100644 --- a/bus/session.conf.in +++ b/bus/session.conf.in @@ -76,5 +76,6 @@ 50000 50000 50000 + 25000 diff --git a/bus/system.conf.in b/bus/system.conf.in index d2f3244b..bccdd977 100644 --- a/bus/system.conf.in +++ b/bus/system.conf.in @@ -126,6 +126,7 @@ + diff --git a/doc/dbus-daemon.1.xml.in b/doc/dbus-daemon.1.xml.in index ae9b5aa3..6511d3dc 100644 --- a/doc/dbus-daemon.1.xml.in +++ b/doc/dbus-daemon.1.xml.in @@ -838,6 +838,9 @@ Available limit names are: "max_replies_per_connection" : max number of pending method replies per connection (number of calls-in-progress) + "max_messages_for_service_per_connection": max number of pending method + calls for a single service per + connection. "reply_timeout" : milliseconds (thousandths) until a method call times out diff --git a/test/data/valid-config-files-system/tmp-session-like-system.conf.in b/test/data/valid-config-files-system/tmp-session-like-system.conf.in index 9665a22a..d59d1b3b 100644 --- a/test/data/valid-config-files-system/tmp-session-like-system.conf.in +++ b/test/data/valid-config-files-system/tmp-session-like-system.conf.in @@ -84,6 +84,7 @@ 50000 50000 50000 + 25000 300000 diff --git a/test/data/valid-config-files/incoming-limit.conf.in b/test/data/valid-config-files/incoming-limit.conf.in index cd813442..ba789545 100644 --- a/test/data/valid-config-files/incoming-limit.conf.in +++ b/test/data/valid-config-files/incoming-limit.conf.in @@ -18,4 +18,5 @@ 1000000 + 500000 diff --git a/test/data/valid-config-files/max-replies-per-connection.conf.in b/test/data/valid-config-files/max-replies-per-connection.conf.in index d4615ed8..79e01abc 100644 --- a/test/data/valid-config-files/max-replies-per-connection.conf.in +++ b/test/data/valid-config-files/max-replies-per-connection.conf.in @@ -15,4 +15,6 @@ 3 + + 10000 diff --git a/test/data/valid-config-files/tmp-session.conf.in b/test/data/valid-config-files/tmp-session.conf.in index d1effae1..206ba29b 100644 --- a/test/data/valid-config-files/tmp-session.conf.in +++ b/test/data/valid-config-files/tmp-session.conf.in @@ -57,4 +57,5 @@ 50000 50000 50000 + 25000