summaryrefslogtreecommitdiff
path: root/src/dbusbind.c
diff options
context:
space:
mode:
authorJan D <jan.h.d@swipnet.se>2010-09-26 18:20:01 +0200
committerJan D <jan.h.d@swipnet.se>2010-09-26 18:20:01 +0200
commit3fad2ad22ee508b6926c71fb87d53728bbc8f240 (patch)
treeeaa1219476afef2e98a481aaa95c00d21436d86d /src/dbusbind.c
parent6303aba12277fcac6a597908fb047560cf7c0c3e (diff)
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.
Diffstat (limited to 'src/dbusbind.c')
-rw-r--r--src/dbusbind.c170
1 files changed, 98 insertions, 72 deletions
diff --git a/src/dbusbind.c b/src/dbusbind.c
index 3b6f0e543b..a8db1c510c 100644
--- a/src/dbusbind.c
+++ b/src/dbusbind.c
@@ -27,6 +27,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "frame.h"
#include "termhooks.h"
#include "keyboard.h"
+#include "process.h"
/* Subroutines. */
@@ -799,71 +800,93 @@ xd_initialize (Lisp_Object bus, int raise_error)
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
-xd_add_watch (DBusWatch *watch, void *data)
+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)
{
- /* 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);
+ /* 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);
+ int fd = dbus_watch_get_fd (watch);
#endif
- XD_DEBUG_MESSAGE ("fd %d", fd);
+ return fd;
+}
- if (fd == -1)
- return FALSE;
- /* Add the file descriptor to input_wait_mask. */
- add_keyboard_wait_descriptor (fd);
- }
+/* Start monitoring WATCH for possible I/O. */
- /* Return. */
+static dbus_bool_t
+xd_add_watch (DBusWatch *watch, void *data)
+{
+ 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 (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 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);
- if (fd == -1)
- return;
+ XD_DEBUG_MESSAGE ("fd %d", fd);
+
+ 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 @@ DEFUN ("dbus-init-bus", Fdbus_init_bus, Sdbus_init_bus, 1, 1, 0,
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 @@ usage: (dbus-call-method-asynchronously BUS SERVICE PATH INTERFACE METHOD HANDLE
result = Qnil;
}
- /* Flush connection to ensure the message is handled. */
- dbus_connection_flush (connection);
-
XD_DEBUG_MESSAGE ("Message sent");
/* Cleanup. */
@@ -1379,9 +1400,6 @@ usage: (dbus-method-return-internal BUS SERIAL SERVICE &rest ARGS) */)
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 @@ usage: (dbus-method-error-internal BUS SERIAL SERVICE &rest ARGS) */)
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 @@ usage: (dbus-send-signal BUS SERVICE PATH INTERFACE SIGNAL &rest ARGS) */)
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 @@ xd_pending_messages (void)
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 @@ xd_read_message (Lisp_Object bus)
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. */