# HG changeset patch # User Jan D # Date 1285518001 -7200 # Node ID c06958da83b5357c870a314a7021b7a6f64291e0 # Parent ab4cdde63001d05ffa054b6444bb1ce76121bccb 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. diff -r ab4cdde63001 -r c06958da83b5 src/ChangeLog --- a/src/ChangeLog Sun Sep 26 17:30:44 2010 +0200 +++ b/src/ChangeLog Sun Sep 26 18:20:01 2010 +0200 @@ -1,3 +1,43 @@ +2010-09-26 Jan Djärv + + * process.h (add_read_fd, delete_read_fd, add_write_fd) + (delete_write_fd): Declare. + + * 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. + + * keyboard.c (readable_events, gobble_input): Remove DBUS code. + + * 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. + 2010-09-26 Dan Nicolaescu * term.c: Do not include sys/ioctl.h, not needed. diff -r ab4cdde63001 -r c06958da83b5 src/dbusbind.c --- 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. */ diff -r ab4cdde63001 -r c06958da83b5 src/keyboard.c --- a/src/keyboard.c Sun Sep 26 17:30:44 2010 +0200 +++ b/src/keyboard.c Sun Sep 26 18:20:01 2010 +0200 @@ -3522,12 +3522,6 @@ static int readable_events (int flags) { -#ifdef HAVE_DBUS - /* Check whether a D-Bus message has arrived. */ - if (xd_pending_messages () > 0) - return 1; -#endif /* HAVE_DBUS */ - if (flags & READABLE_EVENTS_DO_TIMERS_NOW) timer_check (1); @@ -6877,11 +6871,6 @@ void gobble_input (int expected) { -#ifdef HAVE_DBUS - /* Read D-Bus messages. */ - xd_read_queued_messages (); -#endif /* HAVE_DBUS */ - #ifdef SIGIO if (interrupt_input) { diff -r ab4cdde63001 -r c06958da83b5 src/process.c --- a/src/process.c Sun Sep 26 17:30:44 2010 +0200 +++ b/src/process.c Sun Sep 26 18:20:01 2010 +0200 @@ -294,9 +294,9 @@ static SELECT_TYPE non_process_wait_mask; -/* Mask for the gpm mouse input descriptor. */ - -static SELECT_TYPE gpm_wait_mask; +/* Mask for selecting for write. */ + +static SELECT_TYPE write_mask; #ifdef NON_BLOCKING_CONNECT /* Mask of bits indicating the descriptors that we wait for connect to @@ -316,11 +316,8 @@ /* The largest descriptor currently in use for a process object. */ static int max_process_desc; -/* The largest descriptor currently in use for keyboard input. */ -static int max_keyboard_desc; - -/* The largest descriptor currently in use for gpm mouse input. */ -static int max_gpm_desc; +/* The largest descriptor currently in use for input. */ +static int max_input_desc; /* Indexed by descriptor, gives the process (if any) for that descriptor */ Lisp_Object chan_process[MAXDESC]; @@ -366,6 +363,90 @@ static char pty_name[24]; #endif + +struct fd_callback_data +{ + fd_callback func; + void *data; +#define FOR_READ 1 +#define FOR_WRITE 2 + int condition; /* mask of the defines above. */ +} fd_callback_info[MAXDESC]; + + +/* Add a file descriptor FD to be monitored for when read is possible. + When read is possible, call FUNC with argument DATA. */ + +void +add_read_fd (int fd, fd_callback func, void *data) +{ + xassert (fd < MAXDESC); + add_keyboard_wait_descriptor (fd); + + fd_callback_info[fd].func = func; + fd_callback_info[fd].data = data; + fd_callback_info[fd].condition |= FOR_READ; +} + +/* Stop monitoring file descriptor FD for when read is possible. */ + +void +delete_read_fd (int fd) +{ + xassert (fd < MAXDESC); + delete_keyboard_wait_descriptor (fd); + + fd_callback_info[fd].condition &= ~FOR_READ; + if (fd_callback_info[fd].condition == 0) + { + fd_callback_info[fd].func = 0; + fd_callback_info[fd].data = 0; + } +} + +/* Add a file descriptor FD to be monitored for when write is possible. + When write is possible, call FUNC with argument DATA. */ + +void +add_write_fd (int fd, fd_callback func, void *data) +{ + xassert (fd < MAXDESC); + FD_SET (fd, &write_mask); + if (fd > max_input_desc) + max_input_desc = fd; + + fd_callback_info[fd].func = func; + fd_callback_info[fd].data = data; + fd_callback_info[fd].condition |= FOR_WRITE; +} + +/* Stop monitoring file descriptor FD for when write is possible. */ + +void +delete_write_fd (int fd) +{ + int lim = max_input_desc; + + xassert (fd < MAXDESC); + FD_CLR (fd, &write_mask); + fd_callback_info[fd].condition &= ~FOR_WRITE; + if (fd_callback_info[fd].condition == 0) + { + fd_callback_info[fd].func = 0; + fd_callback_info[fd].data = 0; + + if (fd == max_input_desc) + for (fd = lim; fd >= 0; fd--) + if (FD_ISSET (fd, &input_wait_mask) || FD_ISSET (fd, &write_mask)) + { + max_input_desc = fd; + break; + } + + } +} + + /* Compute the Lisp form of the process status, p->status, from the numeric status that was returned by `wait'. */ @@ -3620,6 +3701,7 @@ if (!FD_ISSET (inch, &connect_wait_mask)) { FD_SET (inch, &connect_wait_mask); + FD_SET (inch, &write_mask); num_pending_connects++; } } @@ -4023,6 +4105,7 @@ if (FD_ISSET (inchannel, &connect_wait_mask)) { FD_CLR (inchannel, &connect_wait_mask); + FD_CLR (inchannel, &write_mask); if (--num_pending_connects < 0) abort (); } @@ -4401,10 +4484,8 @@ { register int channel, nfds; SELECT_TYPE Available; -#ifdef NON_BLOCKING_CONNECT - SELECT_TYPE Connecting; - int check_connect; -#endif + SELECT_TYPE Writeok; + int check_write; int check_delay, no_avail; int xerrno; Lisp_Object proc; @@ -4414,9 +4495,7 @@ int count = SPECPDL_INDEX (); FD_ZERO (&Available); -#ifdef NON_BLOCKING_CONNECT - FD_ZERO (&Connecting); -#endif + FD_ZERO (&Writeok); if (time_limit == 0 && microsecs == 0 && wait_proc && !NILP (Vinhibit_quit) && !(CONSP (wait_proc->status) && EQ (XCAR (wait_proc->status), Qexit))) @@ -4552,19 +4631,16 @@ if (update_tick != process_tick) { SELECT_TYPE Atemp; -#ifdef NON_BLOCKING_CONNECT SELECT_TYPE Ctemp; -#endif if (kbd_on_hold_p ()) FD_ZERO (&Atemp); else Atemp = input_wait_mask; - IF_NON_BLOCKING_CONNECT (Ctemp = connect_wait_mask); + Ctemp = write_mask; EMACS_SET_SECS_USECS (timeout, 0, 0); - if ((select (max (max (max_process_desc, max_keyboard_desc), - max_gpm_desc) + 1, + if ((select (max (max_process_desc, max_input_desc) + 1, &Atemp, #ifdef NON_BLOCKING_CONNECT (num_pending_connects > 0 ? &Ctemp : (SELECT_TYPE *)0), @@ -4635,13 +4711,13 @@ break; FD_SET (wait_proc->infd, &Available); check_delay = 0; - IF_NON_BLOCKING_CONNECT (check_connect = 0); + check_write = 0; } else if (!NILP (wait_for_cell)) { Available = non_process_wait_mask; check_delay = 0; - IF_NON_BLOCKING_CONNECT (check_connect = 0); + check_write = 0; } else { @@ -4649,7 +4725,8 @@ Available = non_keyboard_wait_mask; else Available = input_wait_mask; - IF_NON_BLOCKING_CONNECT (check_connect = (num_pending_connects > 0)); + Writeok = write_mask; + check_write = 1; check_delay = wait_channel >= 0 ? 0 : process_output_delay_count; } @@ -4674,10 +4751,6 @@ } else { -#ifdef NON_BLOCKING_CONNECT - if (check_connect) - Connecting = connect_wait_mask; -#endif #ifdef ADAPTIVE_READ_BUFFERING /* Set the timeout for adaptive read buffering if any @@ -4719,15 +4792,10 @@ #else nfds = select #endif - (max (max (max_process_desc, max_keyboard_desc), - max_gpm_desc) + 1, - &Available, -#ifdef NON_BLOCKING_CONNECT - (check_connect ? &Connecting : (SELECT_TYPE *)0), -#else - (SELECT_TYPE *)0, -#endif - (SELECT_TYPE *)0, &timeout); + (max (max_process_desc, max_input_desc) + 1, + &Available, + (check_write ? &Writeok : (SELECT_TYPE *)0), + (SELECT_TYPE *)0, &timeout); } xerrno = errno; @@ -4767,7 +4835,7 @@ if (no_avail) { FD_ZERO (&Available); - IF_NON_BLOCKING_CONNECT (check_connect = 0); + check_write = 0; } #if 0 /* When polling is used, interrupt_input is 0, @@ -4863,12 +4931,26 @@ if (no_avail || nfds == 0) continue; + for (channel = 0; channel <= max_input_desc; ++channel) + { + struct fd_callback_data *d = &fd_callback_info[channel]; + if (FD_ISSET (channel, &Available) + && d->func != 0 + && (d->condition & FOR_READ) != 0) + d->func (channel, d->data, 1); + if (FD_ISSET (channel, &write_mask) + && d->func != 0 + && (d->condition & FOR_WRITE) != 0) + d->func (channel, d->data, 0); + } + /* Really FIRST_PROC_DESC should be 0 on Unix, but this is safer in the short run. */ for (channel = 0; channel <= max_process_desc; channel++) { if (FD_ISSET (channel, &Available) - && FD_ISSET (channel, &non_keyboard_wait_mask)) + && FD_ISSET (channel, &non_keyboard_wait_mask) + && !FD_ISSET (channel, &non_process_wait_mask)) { int nread; @@ -4973,7 +5055,7 @@ } } #ifdef NON_BLOCKING_CONNECT - if (check_connect && FD_ISSET (channel, &Connecting) + if (FD_ISSET (channel, &Writeok) && FD_ISSET (channel, &connect_wait_mask)) { struct Lisp_Process *p; @@ -6745,35 +6827,16 @@ -static int add_gpm_wait_descriptor_called_flag; - void add_gpm_wait_descriptor (int desc) { - if (! add_gpm_wait_descriptor_called_flag) - FD_CLR (0, &input_wait_mask); - add_gpm_wait_descriptor_called_flag = 1; - FD_SET (desc, &input_wait_mask); - FD_SET (desc, &gpm_wait_mask); - if (desc > max_gpm_desc) - max_gpm_desc = desc; + add_keyboard_wait_descriptor (desc); } void delete_gpm_wait_descriptor (int desc) { - int fd; - int lim = max_gpm_desc; - - FD_CLR (desc, &input_wait_mask); - FD_CLR (desc, &non_process_wait_mask); - - if (desc == max_gpm_desc) - for (fd = 0; fd < lim; fd++) - if (FD_ISSET (fd, &input_wait_mask) - && !FD_ISSET (fd, &non_keyboard_wait_mask) - && !FD_ISSET (fd, &non_process_wait_mask)) - max_gpm_desc = fd; + delete_keyboard_wait_descriptor (desc); } /* Return nonzero if *MASK has a bit set @@ -6784,7 +6847,7 @@ { int fd; - for (fd = 0; fd <= max_keyboard_desc; fd++) + for (fd = 0; fd <= max_input_desc; fd++) if (FD_ISSET (fd, mask) && FD_ISSET (fd, &input_wait_mask) && !FD_ISSET (fd, &non_keyboard_wait_mask)) return 1; @@ -7023,12 +7086,10 @@ void add_keyboard_wait_descriptor (int desc) { -#ifdef subprocesses FD_SET (desc, &input_wait_mask); FD_SET (desc, &non_process_wait_mask); - if (desc > max_keyboard_desc) - max_keyboard_desc = desc; -#endif + if (desc > max_input_desc) + max_input_desc = desc; } /* From now on, do not expect DESC to give keyboard input. */ @@ -7036,20 +7097,16 @@ void delete_keyboard_wait_descriptor (int desc) { -#ifdef subprocesses int fd; - int lim = max_keyboard_desc; + int lim = max_input_desc; FD_CLR (desc, &input_wait_mask); FD_CLR (desc, &non_process_wait_mask); - if (desc == max_keyboard_desc) + if (desc == max_input_desc) for (fd = 0; fd < lim; fd++) - if (FD_ISSET (fd, &input_wait_mask) - && !FD_ISSET (fd, &non_keyboard_wait_mask) - && !FD_ISSET (fd, &gpm_wait_mask)) - max_keyboard_desc = fd; -#endif /* subprocesses */ + if (FD_ISSET (fd, &input_wait_mask) || FD_ISSET (fd, &write_mask)) + max_input_desc = fd; } /* Setup coding systems of PROCESS. */ @@ -7306,7 +7363,9 @@ FD_ZERO (&input_wait_mask); FD_ZERO (&non_keyboard_wait_mask); FD_ZERO (&non_process_wait_mask); + FD_ZERO (&write_mask); max_process_desc = 0; + memset (fd_callback_info, 0, sizeof (fd_callback_info)); #ifdef NON_BLOCKING_CONNECT FD_ZERO (&connect_wait_mask); diff -r ab4cdde63001 -r c06958da83b5 src/process.h --- a/src/process.h Sun Sep 26 17:30:44 2010 +0200 +++ b/src/process.h Sun Sep 26 18:20:01 2010 +0200 @@ -192,5 +192,12 @@ extern void unhold_keyboard_input (void); extern int kbd_on_hold_p (void); +typedef void (*fd_callback)(int fd, void *data, int for_read); + +extern void add_read_fd (int fd, fd_callback func, void *data); +extern void delete_read_fd (int fd); +extern void add_write_fd (int fd, fd_callback func, void *data); +extern void delete_write_fd (int fd); + /* arch-tag: dffedfc4-d7bc-4b58-a26f-c16155449c72 (do not change this comment) */