diff src/dbusbind.c @ 110592:c06958da83b5

Add fd handling with callbacks to select, dbus needs it for async operation. * src/dbusbind.c: Include process.h. (dbus_fd_cb, xd_find_watch_fd, xd_toggle_watch) (xd_read_message_1): New functions. (xd_add_watch, xd_remove_watch): Call xd_find_watch_fd. Handle watch for both read and write. (Fdbus_init_bus): Also register xd_toggle_watch. (Fdbus_call_method_asynchronously, Fdbus_method_return_internal) (Fdbus_method_error_internal, Fdbus_send_signal): Remove call to dbus_connection_flush. (xd_read_message): Move most of the code to xd_read_message_1. Call xd_read_message_1 until status is COMPLETE. * src/keyboard.c (readable_events, gobble_input): Remove DBUS code. * src/process.c (gpm_wait_mask, max_gpm_desc): Remove. (write_mask): New variable. (max_input_desc): Renamed from max_keyboard_desc. (fd_callback_info): New variable. (add_read_fd, delete_read_fd, add_write_fd, delete_write_fd): New functions. (Fmake_network_process): FD_SET write_mask. (deactivate_process): FD_CLR write_mask. (wait_reading_process_output): Connecting renamed to Writeok. check_connect removed. check_write is new. Remove references to gpm. Use Writeok/check_write unconditionally (i.e. no #ifdef NON_BLOCKING_CONNECT) instead of Connecting. Loop over file descriptors and call callbacks in fd_callback_info if file descriptor is ready for I/O. (add_gpm_wait_descriptor): Just call add_keyboard_wait_descriptor. (delete_gpm_wait_descriptor): Just call delete_keyboard_wait_descriptor. (keyboard_bit_set): Use max_input_desc. (add_keyboard_wait_descriptor, delete_keyboard_wait_descriptor): Remove #ifdef subprocesses. Use max_input_desc. (init_process): Initialize write_mask and fd_callback_info. * src/process.h (add_read_fd, delete_read_fd, add_write_fd) (delete_write_fd): Declare.
author Jan D <jan.h.d@swipnet.se>
date Sun, 26 Sep 2010 18:20:01 +0200
parents 25b9c8c975be
children 7867879a43ce
line wrap: on
line diff
--- a/src/dbusbind.c	Sun Sep 26 17:30:44 2010 +0200
+++ b/src/dbusbind.c	Sun Sep 26 18:20:01 2010 +0200
@@ -27,6 +27,7 @@
 #include "frame.h"
 #include "termhooks.h"
 #include "keyboard.h"
+#include "process.h"
 
 
 /* Subroutines.  */
@@ -799,71 +800,93 @@
   return connection;
 }
 
+/* Callback called when something is read to read ow write.  */
 
-/* Add connection file descriptor to input_wait_mask, in order to
-   let select() detect, whether a new message has been arrived.  */
-dbus_bool_t
+static void
+dbus_fd_cb (int fd, void *data, int for_read)
+{
+  xd_read_queued_messages ();
+}
+
+/* Return the file descriptor for WATCH, -1 if not found.  */
+
+static int
+xd_find_watch_fd (DBusWatch *watch)
+{
+#if HAVE_DBUS_WATCH_GET_UNIX_FD
+  /* TODO: Reverse these on Win32, which prefers the opposite.  */
+  int fd = dbus_watch_get_unix_fd (watch);
+  if (fd == -1)
+    fd = dbus_watch_get_socket (watch);
+#else
+  int fd = dbus_watch_get_fd (watch);
+#endif
+  return fd;
+}
+
+
+/* Start monitoring WATCH for possible I/O.  */
+
+static dbus_bool_t
 xd_add_watch (DBusWatch *watch, void *data)
 {
-  /* We check only for incoming data.  */
-  if (dbus_watch_get_flags (watch) & DBUS_WATCH_READABLE)
+  unsigned int flags = dbus_watch_get_flags (watch);
+  int fd = xd_find_watch_fd (watch);
+
+  XD_DEBUG_MESSAGE ("fd %d, write %d, enabled %d",
+                    fd, flags & DBUS_WATCH_WRITABLE,
+                    dbus_watch_get_enabled (watch));
+
+  if (fd == -1)
+    return FALSE;
+
+  if (dbus_watch_get_enabled (watch))
     {
-#if HAVE_DBUS_WATCH_GET_UNIX_FD
-      /* TODO: Reverse these on Win32, which prefers the opposite.  */
-      int fd = dbus_watch_get_unix_fd(watch);
-      if (fd == -1)
-	fd = dbus_watch_get_socket(watch);
-#else
-      int fd = dbus_watch_get_fd(watch);
-#endif
-      XD_DEBUG_MESSAGE ("fd %d", fd);
-
-      if (fd == -1)
-	return FALSE;
-
-      /* Add the file descriptor to input_wait_mask.  */
-      add_keyboard_wait_descriptor (fd);
+      if (flags & DBUS_WATCH_WRITABLE)
+        add_write_fd (fd, dbus_fd_cb, NULL);
+      if (flags & DBUS_WATCH_READABLE)
+        add_read_fd (fd, dbus_fd_cb, NULL);
     }
-
-  /* Return.  */
   return TRUE;
 }
 
-/* Remove connection file descriptor from input_wait_mask.  DATA is
-   the used bus, either a string or QCdbus_system_bus or
+/* Stop monitoring WATCH for possible I/O.
+   DATA is the used bus, either a string or QCdbus_system_bus or
    QCdbus_session_bus.  */
-void
+
+static void
 xd_remove_watch (DBusWatch *watch, void *data)
 {
-  /* We check only for incoming data.  */
-  if (dbus_watch_get_flags (watch) & DBUS_WATCH_READABLE)
-    {
-#if HAVE_DBUS_WATCH_GET_UNIX_FD
-      /* TODO: Reverse these on Win32, which prefers the opposite.  */
-      int fd = dbus_watch_get_unix_fd(watch);
-      if (fd == -1)
-	fd = dbus_watch_get_socket(watch);
-#else
-      int fd = dbus_watch_get_fd(watch);
-#endif
-      XD_DEBUG_MESSAGE ("fd %d", fd);
+  unsigned int flags = dbus_watch_get_flags (watch);
+  int fd = xd_find_watch_fd (watch);
+
+  XD_DEBUG_MESSAGE ("fd %d", fd);
+
+  if (fd == -1) return;
 
-      if (fd == -1)
-	return;
 
-      /* Unset session environment.  */
-      if ((data != NULL) && (data == (void*) XHASH (QCdbus_session_bus)))
-	{
-	  XD_DEBUG_MESSAGE ("unsetenv DBUS_SESSION_BUS_ADDRESS");
-	  unsetenv ("DBUS_SESSION_BUS_ADDRESS");
-	}
-
-      /* Remove the file descriptor from input_wait_mask.  */
-      delete_keyboard_wait_descriptor (fd);
+  /* Unset session environment.  */
+  if (data != NULL && data == (void*) XHASH (QCdbus_session_bus))
+    {
+      XD_DEBUG_MESSAGE ("unsetenv DBUS_SESSION_BUS_ADDRESS");
+      unsetenv ("DBUS_SESSION_BUS_ADDRESS");
     }
 
-  /* Return.  */
-  return;
+  if (flags & DBUS_WATCH_WRITABLE)
+    delete_write_fd (fd);
+  if (flags & DBUS_WATCH_READABLE)
+    delete_read_fd (fd);
+}
+
+/* Toggle monitoring WATCH for possible I/O.  */
+
+static void
+xd_toggle_watch (DBusWatch *watch, void *data)
+{
+  if (dbus_watch_get_enabled (watch))
+    xd_add_watch (watch, data);
+  else
+    xd_remove_watch (watch, data);
 }
 
 DEFUN ("dbus-init-bus", Fdbus_init_bus, Sdbus_init_bus, 1, 1, 0,
@@ -880,7 +903,8 @@
   if (!dbus_connection_set_watch_functions (connection,
 					    xd_add_watch,
 					    xd_remove_watch,
-					    NULL, (void*) XHASH (bus), NULL))
+                                            xd_toggle_watch,
+					    (void*) XHASH (bus), NULL))
     XD_SIGNAL1 (build_string ("Cannot add watch functions"));
 
   /* Add bus to list of registered buses.  */
@@ -1288,9 +1312,6 @@
       result = Qnil;
     }
 
-  /* Flush connection to ensure the message is handled.  */
-  dbus_connection_flush (connection);
-
   XD_DEBUG_MESSAGE ("Message sent");
 
   /* Cleanup.  */
@@ -1379,9 +1400,6 @@
   if (!dbus_connection_send (connection, dmessage, NULL))
     XD_SIGNAL1 (build_string ("Cannot send message"));
 
-  /* Flush connection to ensure the message is handled.  */
-  dbus_connection_flush (connection);
-
   XD_DEBUG_MESSAGE ("Message sent");
 
   /* Cleanup.  */
@@ -1471,9 +1489,6 @@
   if (!dbus_connection_send (connection, dmessage, NULL))
     XD_SIGNAL1 (build_string ("Cannot send message"));
 
-  /* Flush connection to ensure the message is handled.  */
-  dbus_connection_flush (connection);
-
   XD_DEBUG_MESSAGE ("Message sent");
 
   /* Cleanup.  */
@@ -1589,9 +1604,6 @@
   if (!dbus_connection_send (connection, dmessage, NULL))
     XD_SIGNAL1 (build_string ("Cannot send message"));
 
-  /* Flush connection to ensure the message is handled.  */
-  dbus_connection_flush (connection);
-
   XD_DEBUG_MESSAGE ("Signal sent");
 
   /* Cleanup.  */
@@ -1645,32 +1657,27 @@
   return FALSE;
 }
 
-/* Read queued incoming message of the D-Bus BUS.  BUS is either a
-   Lisp symbol, :system or :session, or a string denoting the bus
-   address.  */
-static Lisp_Object
-xd_read_message (Lisp_Object bus)
+/* Read one queued incoming message of the D-Bus BUS.
+   BUS is either a Lisp symbol, :system or :session, or a string denoting
+   the bus address.  */
+
+static void
+xd_read_message_1 (DBusConnection *connection, Lisp_Object bus)
 {
   Lisp_Object args, key, value;
   struct gcpro gcpro1;
   struct input_event event;
-  DBusConnection *connection;
   DBusMessage *dmessage;
   DBusMessageIter iter;
   unsigned int dtype;
   int mtype, serial;
   const char *uname, *path, *interface, *member;
 
-  /* Open a connection to the bus.  */
-  connection = xd_initialize (bus, TRUE);
-
-  /* Non blocking read of the next available message.  */
-  dbus_connection_read_write (connection, 0);
   dmessage = dbus_connection_pop_message (connection);
 
   /* Return if there is no queued message.  */
   if (dmessage == NULL)
-    return Qnil;
+    return;
 
   /* Collect the parameters.  */
   args = Qnil;
@@ -1801,7 +1808,26 @@
  cleanup:
   dbus_message_unref (dmessage);
 
-  RETURN_UNGCPRO (Qnil);
+  UNGCPRO;
+}
+
+/* Read queued incoming messages of the D-Bus BUS.
+   BUS is either a Lisp symbol, :system or :session, or a string denoting
+   the bus address.  */
+
+static Lisp_Object
+xd_read_message (Lisp_Object bus)
+{
+  /* Open a connection to the bus.  */
+  DBusConnection *connection = xd_initialize (bus, TRUE);
+
+  /* Non blocking read of the next available message.  */
+  dbus_connection_read_write (connection, 0);
+
+  while (dbus_connection_get_dispatch_status (connection)
+         != DBUS_DISPATCH_COMPLETE)
+    xd_read_message_1 (connection, bus);
+  return Qnil;
 }
 
 /* Read queued incoming messages from all buses.  */