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 cb388473..4e26e091 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; @@ -2189,6 +2195,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; @@ -3496,6 +3508,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 dea09bd5..a442da5a 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 5bf93b93..0fe13b83 100644 --- a/doc/dbus-daemon.1.xml.in +++ b/doc/dbus-daemon.1.xml.in @@ -854,6 +854,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