diff options
| author | Jan D | 2010-09-26 18:20:01 +0200 |
|---|---|---|
| committer | Jan D | 2010-09-26 18:20:01 +0200 |
| commit | 3fad2ad22ee508b6926c71fb87d53728bbc8f240 (patch) | |
| tree | eaa1219476afef2e98a481aaa95c00d21436d86d /src/dbusbind.c | |
| parent | 6303aba12277fcac6a597908fb047560cf7c0c3e (diff) | |
| download | emacs-3fad2ad22ee508b6926c71fb87d53728bbc8f240.tar.gz emacs-3fad2ad22ee508b6926c71fb87d53728bbc8f240.zip | |
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.c | 170 |
1 files changed, 98 insertions, 72 deletions
diff --git a/src/dbusbind.c b/src/dbusbind.c index 3b6f0e543bb..a8db1c510c7 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/>. */ | |||
| 27 | #include "frame.h" | 27 | #include "frame.h" |
| 28 | #include "termhooks.h" | 28 | #include "termhooks.h" |
| 29 | #include "keyboard.h" | 29 | #include "keyboard.h" |
| 30 | #include "process.h" | ||
| 30 | 31 | ||
| 31 | 32 | ||
| 32 | /* Subroutines. */ | 33 | /* Subroutines. */ |
| @@ -799,71 +800,93 @@ xd_initialize (Lisp_Object bus, int raise_error) | |||
| 799 | return connection; | 800 | return connection; |
| 800 | } | 801 | } |
| 801 | 802 | ||
| 803 | /* Callback called when something is read to read ow write. */ | ||
| 802 | 804 | ||
| 803 | /* Add connection file descriptor to input_wait_mask, in order to | 805 | static void |
| 804 | let select() detect, whether a new message has been arrived. */ | 806 | dbus_fd_cb (int fd, void *data, int for_read) |
| 805 | dbus_bool_t | 807 | { |
| 806 | xd_add_watch (DBusWatch *watch, void *data) | 808 | xd_read_queued_messages (); |
| 809 | } | ||
| 810 | |||
| 811 | /* Return the file descriptor for WATCH, -1 if not found. */ | ||
| 812 | |||
| 813 | static int | ||
| 814 | xd_find_watch_fd (DBusWatch *watch) | ||
| 807 | { | 815 | { |
| 808 | /* We check only for incoming data. */ | ||
| 809 | if (dbus_watch_get_flags (watch) & DBUS_WATCH_READABLE) | ||
| 810 | { | ||
| 811 | #if HAVE_DBUS_WATCH_GET_UNIX_FD | 816 | #if HAVE_DBUS_WATCH_GET_UNIX_FD |
| 812 | /* TODO: Reverse these on Win32, which prefers the opposite. */ | 817 | /* TODO: Reverse these on Win32, which prefers the opposite. */ |
| 813 | int fd = dbus_watch_get_unix_fd(watch); | 818 | int fd = dbus_watch_get_unix_fd (watch); |
| 814 | if (fd == -1) | 819 | if (fd == -1) |
| 815 | fd = dbus_watch_get_socket(watch); | 820 | fd = dbus_watch_get_socket (watch); |
| 816 | #else | 821 | #else |
| 817 | int fd = dbus_watch_get_fd(watch); | 822 | int fd = dbus_watch_get_fd (watch); |
| 818 | #endif | 823 | #endif |
| 819 | XD_DEBUG_MESSAGE ("fd %d", fd); | 824 | return fd; |
| 825 | } | ||
| 820 | 826 | ||
| 821 | if (fd == -1) | ||
| 822 | return FALSE; | ||
| 823 | 827 | ||
| 824 | /* Add the file descriptor to input_wait_mask. */ | 828 | /* Start monitoring WATCH for possible I/O. */ |
| 825 | add_keyboard_wait_descriptor (fd); | ||
| 826 | } | ||
| 827 | 829 | ||
| 828 | /* Return. */ | 830 | static dbus_bool_t |
| 831 | xd_add_watch (DBusWatch *watch, void *data) | ||
| 832 | { | ||
| 833 | unsigned int flags = dbus_watch_get_flags (watch); | ||
| 834 | int fd = xd_find_watch_fd (watch); | ||
| 835 | |||
| 836 | XD_DEBUG_MESSAGE ("fd %d, write %d, enabled %d", | ||
| 837 | fd, flags & DBUS_WATCH_WRITABLE, | ||
| 838 | dbus_watch_get_enabled (watch)); | ||
| 839 | |||
| 840 | if (fd == -1) | ||
| 841 | return FALSE; | ||
| 842 | |||
| 843 | if (dbus_watch_get_enabled (watch)) | ||
| 844 | { | ||
| 845 | if (flags & DBUS_WATCH_WRITABLE) | ||
| 846 | add_write_fd (fd, dbus_fd_cb, NULL); | ||
| 847 | if (flags & DBUS_WATCH_READABLE) | ||
| 848 | add_read_fd (fd, dbus_fd_cb, NULL); | ||
| 849 | } | ||
| 829 | return TRUE; | 850 | return TRUE; |
| 830 | } | 851 | } |
| 831 | 852 | ||
| 832 | /* Remove connection file descriptor from input_wait_mask. DATA is | 853 | /* Stop monitoring WATCH for possible I/O. |
| 833 | the used bus, either a string or QCdbus_system_bus or | 854 | DATA is the used bus, either a string or QCdbus_system_bus or |
| 834 | QCdbus_session_bus. */ | 855 | QCdbus_session_bus. */ |
| 835 | void | 856 | |
| 857 | static void | ||
| 836 | xd_remove_watch (DBusWatch *watch, void *data) | 858 | xd_remove_watch (DBusWatch *watch, void *data) |
| 837 | { | 859 | { |
| 838 | /* We check only for incoming data. */ | 860 | unsigned int flags = dbus_watch_get_flags (watch); |
| 839 | if (dbus_watch_get_flags (watch) & DBUS_WATCH_READABLE) | 861 | int fd = xd_find_watch_fd (watch); |
| 840 | { | ||
| 841 | #if HAVE_DBUS_WATCH_GET_UNIX_FD | ||
| 842 | /* TODO: Reverse these on Win32, which prefers the opposite. */ | ||
| 843 | int fd = dbus_watch_get_unix_fd(watch); | ||
| 844 | if (fd == -1) | ||
| 845 | fd = dbus_watch_get_socket(watch); | ||
| 846 | #else | ||
| 847 | int fd = dbus_watch_get_fd(watch); | ||
| 848 | #endif | ||
| 849 | XD_DEBUG_MESSAGE ("fd %d", fd); | ||
| 850 | 862 | ||
| 851 | if (fd == -1) | 863 | XD_DEBUG_MESSAGE ("fd %d", fd); |
| 852 | return; | 864 | |
| 865 | if (fd == -1) return; | ||
| 853 | 866 | ||
| 854 | /* Unset session environment. */ | ||
| 855 | if ((data != NULL) && (data == (void*) XHASH (QCdbus_session_bus))) | ||
| 856 | { | ||
| 857 | XD_DEBUG_MESSAGE ("unsetenv DBUS_SESSION_BUS_ADDRESS"); | ||
| 858 | unsetenv ("DBUS_SESSION_BUS_ADDRESS"); | ||
| 859 | } | ||
| 860 | 867 | ||
| 861 | /* Remove the file descriptor from input_wait_mask. */ | 868 | /* Unset session environment. */ |
| 862 | delete_keyboard_wait_descriptor (fd); | 869 | if (data != NULL && data == (void*) XHASH (QCdbus_session_bus)) |
| 870 | { | ||
| 871 | XD_DEBUG_MESSAGE ("unsetenv DBUS_SESSION_BUS_ADDRESS"); | ||
| 872 | unsetenv ("DBUS_SESSION_BUS_ADDRESS"); | ||
| 863 | } | 873 | } |
| 864 | 874 | ||
| 865 | /* Return. */ | 875 | if (flags & DBUS_WATCH_WRITABLE) |
| 866 | return; | 876 | delete_write_fd (fd); |
| 877 | if (flags & DBUS_WATCH_READABLE) | ||
| 878 | delete_read_fd (fd); | ||
| 879 | } | ||
| 880 | |||
| 881 | /* Toggle monitoring WATCH for possible I/O. */ | ||
| 882 | |||
| 883 | static void | ||
| 884 | xd_toggle_watch (DBusWatch *watch, void *data) | ||
| 885 | { | ||
| 886 | if (dbus_watch_get_enabled (watch)) | ||
| 887 | xd_add_watch (watch, data); | ||
| 888 | else | ||
| 889 | xd_remove_watch (watch, data); | ||
| 867 | } | 890 | } |
| 868 | 891 | ||
| 869 | DEFUN ("dbus-init-bus", Fdbus_init_bus, Sdbus_init_bus, 1, 1, 0, | 892 | 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, | |||
| 880 | if (!dbus_connection_set_watch_functions (connection, | 903 | if (!dbus_connection_set_watch_functions (connection, |
| 881 | xd_add_watch, | 904 | xd_add_watch, |
| 882 | xd_remove_watch, | 905 | xd_remove_watch, |
| 883 | NULL, (void*) XHASH (bus), NULL)) | 906 | xd_toggle_watch, |
| 907 | (void*) XHASH (bus), NULL)) | ||
| 884 | XD_SIGNAL1 (build_string ("Cannot add watch functions")); | 908 | XD_SIGNAL1 (build_string ("Cannot add watch functions")); |
| 885 | 909 | ||
| 886 | /* Add bus to list of registered buses. */ | 910 | /* Add bus to list of registered buses. */ |
| @@ -1288,9 +1312,6 @@ usage: (dbus-call-method-asynchronously BUS SERVICE PATH INTERFACE METHOD HANDLE | |||
| 1288 | result = Qnil; | 1312 | result = Qnil; |
| 1289 | } | 1313 | } |
| 1290 | 1314 | ||
| 1291 | /* Flush connection to ensure the message is handled. */ | ||
| 1292 | dbus_connection_flush (connection); | ||
| 1293 | |||
| 1294 | XD_DEBUG_MESSAGE ("Message sent"); | 1315 | XD_DEBUG_MESSAGE ("Message sent"); |
| 1295 | 1316 | ||
| 1296 | /* Cleanup. */ | 1317 | /* Cleanup. */ |
| @@ -1379,9 +1400,6 @@ usage: (dbus-method-return-internal BUS SERIAL SERVICE &rest ARGS) */) | |||
| 1379 | if (!dbus_connection_send (connection, dmessage, NULL)) | 1400 | if (!dbus_connection_send (connection, dmessage, NULL)) |
| 1380 | XD_SIGNAL1 (build_string ("Cannot send message")); | 1401 | XD_SIGNAL1 (build_string ("Cannot send message")); |
| 1381 | 1402 | ||
| 1382 | /* Flush connection to ensure the message is handled. */ | ||
| 1383 | dbus_connection_flush (connection); | ||
| 1384 | |||
| 1385 | XD_DEBUG_MESSAGE ("Message sent"); | 1403 | XD_DEBUG_MESSAGE ("Message sent"); |
| 1386 | 1404 | ||
| 1387 | /* Cleanup. */ | 1405 | /* Cleanup. */ |
| @@ -1471,9 +1489,6 @@ usage: (dbus-method-error-internal BUS SERIAL SERVICE &rest ARGS) */) | |||
| 1471 | if (!dbus_connection_send (connection, dmessage, NULL)) | 1489 | if (!dbus_connection_send (connection, dmessage, NULL)) |
| 1472 | XD_SIGNAL1 (build_string ("Cannot send message")); | 1490 | XD_SIGNAL1 (build_string ("Cannot send message")); |
| 1473 | 1491 | ||
| 1474 | /* Flush connection to ensure the message is handled. */ | ||
| 1475 | dbus_connection_flush (connection); | ||
| 1476 | |||
| 1477 | XD_DEBUG_MESSAGE ("Message sent"); | 1492 | XD_DEBUG_MESSAGE ("Message sent"); |
| 1478 | 1493 | ||
| 1479 | /* Cleanup. */ | 1494 | /* Cleanup. */ |
| @@ -1589,9 +1604,6 @@ usage: (dbus-send-signal BUS SERVICE PATH INTERFACE SIGNAL &rest ARGS) */) | |||
| 1589 | if (!dbus_connection_send (connection, dmessage, NULL)) | 1604 | if (!dbus_connection_send (connection, dmessage, NULL)) |
| 1590 | XD_SIGNAL1 (build_string ("Cannot send message")); | 1605 | XD_SIGNAL1 (build_string ("Cannot send message")); |
| 1591 | 1606 | ||
| 1592 | /* Flush connection to ensure the message is handled. */ | ||
| 1593 | dbus_connection_flush (connection); | ||
| 1594 | |||
| 1595 | XD_DEBUG_MESSAGE ("Signal sent"); | 1607 | XD_DEBUG_MESSAGE ("Signal sent"); |
| 1596 | 1608 | ||
| 1597 | /* Cleanup. */ | 1609 | /* Cleanup. */ |
| @@ -1645,32 +1657,27 @@ xd_pending_messages (void) | |||
| 1645 | return FALSE; | 1657 | return FALSE; |
| 1646 | } | 1658 | } |
| 1647 | 1659 | ||
| 1648 | /* Read queued incoming message of the D-Bus BUS. BUS is either a | 1660 | /* Read one queued incoming message of the D-Bus BUS. |
| 1649 | Lisp symbol, :system or :session, or a string denoting the bus | 1661 | BUS is either a Lisp symbol, :system or :session, or a string denoting |
| 1650 | address. */ | 1662 | the bus address. */ |
| 1651 | static Lisp_Object | 1663 | |
| 1652 | xd_read_message (Lisp_Object bus) | 1664 | static void |
| 1665 | xd_read_message_1 (DBusConnection *connection, Lisp_Object bus) | ||
| 1653 | { | 1666 | { |
| 1654 | Lisp_Object args, key, value; | 1667 | Lisp_Object args, key, value; |
| 1655 | struct gcpro gcpro1; | 1668 | struct gcpro gcpro1; |
| 1656 | struct input_event event; | 1669 | struct input_event event; |
| 1657 | DBusConnection *connection; | ||
| 1658 | DBusMessage *dmessage; | 1670 | DBusMessage *dmessage; |
| 1659 | DBusMessageIter iter; | 1671 | DBusMessageIter iter; |
| 1660 | unsigned int dtype; | 1672 | unsigned int dtype; |
| 1661 | int mtype, serial; | 1673 | int mtype, serial; |
| 1662 | const char *uname, *path, *interface, *member; | 1674 | const char *uname, *path, *interface, *member; |
| 1663 | 1675 | ||
| 1664 | /* Open a connection to the bus. */ | ||
| 1665 | connection = xd_initialize (bus, TRUE); | ||
| 1666 | |||
| 1667 | /* Non blocking read of the next available message. */ | ||
| 1668 | dbus_connection_read_write (connection, 0); | ||
| 1669 | dmessage = dbus_connection_pop_message (connection); | 1676 | dmessage = dbus_connection_pop_message (connection); |
| 1670 | 1677 | ||
| 1671 | /* Return if there is no queued message. */ | 1678 | /* Return if there is no queued message. */ |
| 1672 | if (dmessage == NULL) | 1679 | if (dmessage == NULL) |
| 1673 | return Qnil; | 1680 | return; |
| 1674 | 1681 | ||
| 1675 | /* Collect the parameters. */ | 1682 | /* Collect the parameters. */ |
| 1676 | args = Qnil; | 1683 | args = Qnil; |
| @@ -1801,7 +1808,26 @@ xd_read_message (Lisp_Object bus) | |||
| 1801 | cleanup: | 1808 | cleanup: |
| 1802 | dbus_message_unref (dmessage); | 1809 | dbus_message_unref (dmessage); |
| 1803 | 1810 | ||
| 1804 | RETURN_UNGCPRO (Qnil); | 1811 | UNGCPRO; |
| 1812 | } | ||
| 1813 | |||
| 1814 | /* Read queued incoming messages of the D-Bus BUS. | ||
| 1815 | BUS is either a Lisp symbol, :system or :session, or a string denoting | ||
| 1816 | the bus address. */ | ||
| 1817 | |||
| 1818 | static Lisp_Object | ||
| 1819 | xd_read_message (Lisp_Object bus) | ||
| 1820 | { | ||
| 1821 | /* Open a connection to the bus. */ | ||
| 1822 | DBusConnection *connection = xd_initialize (bus, TRUE); | ||
| 1823 | |||
| 1824 | /* Non blocking read of the next available message. */ | ||
| 1825 | dbus_connection_read_write (connection, 0); | ||
| 1826 | |||
| 1827 | while (dbus_connection_get_dispatch_status (connection) | ||
| 1828 | != DBUS_DISPATCH_COMPLETE) | ||
| 1829 | xd_read_message_1 (connection, bus); | ||
| 1830 | return Qnil; | ||
| 1805 | } | 1831 | } |
| 1806 | 1832 | ||
| 1807 | /* Read queued incoming messages from all buses. */ | 1833 | /* Read queued incoming messages from all buses. */ |