diff --git a/gio/gapplicationimpl-dbus.c b/gio/gapplicationimpl-dbus.c
index 406b839..21cb595 100644
--- a/gio/gapplicationimpl-dbus.c
+++ b/gio/gapplicationimpl-dbus.c
@@ -27,6 +27,7 @@
 #include "gdbusconnection.h"
 #include "gdbusintrospection.h"
 #include "gdbuserror.h"
+#include "gdbusmessage.h"
 
 #include <string.h>
 #include <stdio.h>
@@ -154,8 +155,82 @@ struct _GApplicationImpl
 
   GHashTable      *actions;
   guint            signal_id;
+
+  guint            queue_filter_id;
+  GQueue          *queue_incoming_messages;
 };
 
+G_LOCK_DEFINE_STATIC (queue_lock);
+
+static GDBusMessage *
+filter_func (GDBusConnection *connection,
+             GDBusMessage    *message,
+             gboolean         incoming,
+             gpointer         user_data)
+{
+  GApplicationImpl *impl = user_data;
+  GDBusMessage *ret;
+
+  G_LOCK (queue_lock);
+  ret = NULL;
+
+  /* Ideally we'd only queue up incoming messages for impl->bus_name but unfortunately
+   * the bus does not pass the well-known name. So we just queue up all incoming method
+   * calls...
+   */
+  if (!(impl->queue_incoming_messages != NULL &&
+        incoming &&
+        g_dbus_message_get_message_type (message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL))
+    {
+      ret = message;
+      goto out;
+    }
+
+  g_queue_push_tail (impl->queue_incoming_messages, message);
+
+ out:
+  G_UNLOCK (queue_lock);
+  return ret;
+}
+
+static void
+setup_filter (GApplicationImpl *impl)
+{
+  G_LOCK (queue_lock);
+  g_assert_cmpint (impl->queue_filter_id, ==, 0);
+  impl->queue_filter_id = g_dbus_connection_add_filter (impl->session_bus,
+                                                        filter_func,
+                                                        impl,
+                                                        NULL); /* GDestroyNotify */
+  g_assert_cmpint (impl->queue_filter_id, !=, 0);
+  impl->queue_incoming_messages = g_queue_new ();
+  G_UNLOCK (queue_lock);
+}
+
+static void
+teardown_filter (GApplicationImpl *impl)
+{
+  GQueue *q;
+  GDBusMessage *message;
+
+  G_LOCK (queue_lock);
+  g_assert_cmpint (impl->queue_filter_id, !=, 0);
+  g_dbus_connection_remove_filter (impl->session_bus, impl->queue_filter_id);
+  q = impl->queue_incoming_messages;
+  impl->queue_incoming_messages = NULL;
+  impl->queue_filter_id = 0;
+  G_UNLOCK (queue_lock);
+
+  /* repost all incoming messages without lock held */
+  g_print ("repost messages\n");
+  while ((message = g_queue_pop_head (q)) != NULL)
+    {
+      g_print ("TODO: repost message %p\n", message);
+      g_object_unref (message);
+    }
+  g_queue_free (q);
+}
+
 
 static GApplicationCommandLine *
 g_dbus_command_line_new (GDBusMethodInvocation *invocation);
@@ -609,6 +684,8 @@ g_application_impl_register (GApplication       *application,
           return NULL;
         }
 
+      setup_filter (impl);
+
       /* DBUS_NAME_FLAG_DO_NOT_QUEUE: 0x4 */
       reply = g_dbus_connection_call_sync (impl->session_bus,
                                            "org.freedesktop.DBus",
@@ -623,6 +700,8 @@ g_application_impl_register (GApplication       *application,
 
       if (reply == NULL)
         {
+          teardown_filter (impl);
+
           g_dbus_connection_unregister_object (impl->session_bus,
                                                impl->object_id);
           impl->object_id = 0;
@@ -656,6 +735,7 @@ g_application_impl_register (GApplication       *application,
         }
 
       /* We didn't make it.  Drop our service-side stuff. */
+      teardown_filter (impl);
       g_dbus_connection_unregister_object (impl->session_bus,
                                            impl->object_id);
       impl->object_id = 0;
