From c8ca4ce89c4f4ab4a2a3814c317dcfe2f5d8d3ca Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Fri, 1 Jul 2016 16:25:10 +0100 Subject: [PATCH] dbus-daemon test: attempt to reproduce #95263 Signed-off-by: Simon McVittie --- .../valid-config-files/pending-fd-timeout.conf.in | 3 + test/dbus-daemon.c | 85 +++++++++++++++++++++- 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/test/data/valid-config-files/pending-fd-timeout.conf.in b/test/data/valid-config-files/pending-fd-timeout.conf.in index 849d885..a21482a 100644 --- a/test/data/valid-config-files/pending-fd-timeout.conf.in +++ b/test/data/valid-config-files/pending-fd-timeout.conf.in @@ -17,4 +17,7 @@ 500 + + + 1000000000 diff --git a/test/dbus-daemon.c b/test/dbus-daemon.c index 029e077..c11cb2a 100644 --- a/test/dbus-daemon.c +++ b/test/dbus-daemon.c @@ -200,6 +200,9 @@ setup (Fixture *f, static void add_echo_filter (Fixture *f) { + if (f->right_conn_echo) + return; + if (!dbus_connection_add_filter (f->right_conn, echo_filter, f, NULL)) g_error ("OOM"); @@ -981,23 +984,103 @@ send_all_with_fd (GSocket *socket, } static void +pc_dec_in_flight (DBusPendingCall *pc, + void *data) +{ + guint *in_flight_p = data; + + test_progress ('-'); + (*in_flight_p)--; +} + +static void test_pending_fd_timeout (Fixture *f, gconstpointer context) { GError *error = NULL; gint64 start; - int fd; + int fd = 2; /* stderr */ GSocket *socket; gboolean have_mem; gboolean disconnected = FALSE; + guint in_flight = 0; if (f->skip) return; + add_echo_filter (f); + have_mem = dbus_connection_add_filter (f->left_conn, wait_for_disconnected_cb, &disconnected, NULL); g_assert (have_mem); + /* A connection that constantly sends fds should not get kicked off + * the bus. (The left connection is emulating systemd-logind under + * really heavy load here.) */ + + start = g_get_monotonic_time (); + + while (g_get_monotonic_time () < start + G_USEC_PER_SEC) + { + DBusMessage *m = dbus_message_new_method_call ( + dbus_bus_get_unique_name (f->right_conn), "/", + "com.example", "Spam"); + DBusPendingCall *pc; + + test_progress ('+'); + + if (m == NULL) + g_error ("OOM"); + + dbus_message_set_no_reply (m, TRUE); + + /* Make sure we don't run out of fds altogether; assume we have at + * least 1024 available, and reserve 24 for connections etc. */ + while (in_flight >= 1000) + { + test_progress ('W'); + test_main_context_iterate (f->ctx, TRUE); + } + + in_flight++; + + if (!dbus_message_append_args (m, + DBUS_TYPE_UNIX_FD, &fd, + DBUS_TYPE_INVALID)) + g_error ("OOM"); + + if (!dbus_connection_send_with_reply (f->left_conn, m, &pc, + DBUS_TIMEOUT_INFINITE) || + pc == NULL) + g_error ("OOM"); + + if (dbus_pending_call_get_completed (pc)) + pc_dec_in_flight (pc, &in_flight); + else if (!dbus_pending_call_set_notify (pc, pc_dec_in_flight, &in_flight, + NULL)) + g_error ("OOM"); + + dbus_pending_call_unref (pc); + dbus_message_unref (m); + } + + while (in_flight > 0) + { + test_progress ('.'); + test_main_context_iterate (f->ctx, TRUE); + } + + test_progress ('\n'); + + /* We should not have been disconnected. */ + g_assert (!disconnected); + test_echo (f, context); + g_assert (!disconnected); + + /* Conversely, the connection *should* get disconnected if it gets + * halfway through sending a message with an attached fd, and then gets + * stuck. */ + /* This is not API. Never do this. */ if (!dbus_connection_get_socket (f->left_conn, &fd)) -- 2.8.1