From 113b2e27726c5d95c31034dc5e9db1e8b985c963 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 11 May 2011 10:28:47 -0400 Subject: [PATCH] keyboard: handle kernel terminal EIO better In commit 89096d735f78fab300248962030d6554f9894011 we added reopen retries when the kernel returns EIO to ply-terminal.c. This is because when the kernel is closing a tty down, that tty is unavailable to userspace to reopen. Unfortunately, that commit neglected to inform the ply-keyboard part of the code when the terminal retry was successful. The upshot of this, is that if plymouthd needs to retry opening the tty, then the splash screens lose control over the keyboard. This commit changes how input notification is sent to the keyboard handling code, so the tty disconnects are transparent. --- src/libply-splash-core/ply-keyboard.c | 27 ++------- src/libply-splash-core/ply-terminal.c | 100 +++++++++++++++++++++++++++++++- src/libply-splash-core/ply-terminal.h | 10 +++- 3 files changed, 112 insertions(+), 25 deletions(-) diff --git a/src/libply-splash-core/ply-keyboard.c b/src/libply-splash-core/ply-keyboard.c index b5b4c39..624f906 100644 --- a/src/libply-splash-core/ply-keyboard.c +++ b/src/libply-splash-core/ply-keyboard.c @@ -65,7 +65,6 @@ typedef enum typedef struct { ply_terminal_t *terminal; - ply_fd_watch_t *input_watch; ply_buffer_t *key_buffer; } ply_keyboard_terminal_provider_t; @@ -342,15 +341,6 @@ on_terminal_data (ply_keyboard_t *keyboard) on_key_event (keyboard, keyboard->provider.if_terminal->key_buffer); } -static void -on_terminal_disconnected (ply_keyboard_t *keyboard) -{ - ply_trace ("keyboard input terminal watch invalidated, rewatching"); - keyboard->provider.if_terminal->input_watch = NULL; - - ply_keyboard_watch_for_terminal_input (keyboard); -} - static bool ply_keyboard_watch_for_terminal_input (ply_keyboard_t *keyboard) { @@ -366,10 +356,9 @@ ply_keyboard_watch_for_terminal_input (ply_keyboard_t *keyboard) return false; } - keyboard->provider.if_terminal->input_watch = ply_event_loop_watch_fd (keyboard->loop, terminal_fd, PLY_EVENT_LOOP_FD_STATUS_HAS_DATA, - (ply_event_handler_t) on_terminal_data, - (ply_event_handler_t) on_terminal_disconnected, - keyboard); + ply_terminal_watch_for_input (keyboard->provider.if_terminal->terminal, + (ply_terminal_input_handler_t) on_terminal_data, + keyboard); return true; } @@ -377,12 +366,10 @@ ply_keyboard_watch_for_terminal_input (ply_keyboard_t *keyboard) static void ply_keyboard_stop_watching_for_terminal_input (ply_keyboard_t *keyboard) { - if (keyboard->provider.if_terminal->input_watch == NULL) - return; - - ply_event_loop_stop_watching_fd (keyboard->loop, - keyboard->provider.if_terminal->input_watch); - keyboard->provider.if_terminal->input_watch = NULL; + ply_terminal_stop_watching_for_input (keyboard->provider.if_terminal->terminal, + (ply_terminal_input_handler_t) + on_terminal_data, + keyboard); } bool diff --git a/src/libply-splash-core/ply-terminal.c b/src/libply-splash-core/ply-terminal.c index c11a6dd..8876aa0 100644 --- a/src/libply-splash-core/ply-terminal.c +++ b/src/libply-splash-core/ply-terminal.c @@ -60,6 +60,12 @@ typedef struct { + ply_terminal_input_handler_t handler; + void *user_data; +} ply_terminal_input_closure_t; + +typedef struct +{ ply_terminal_active_vt_changed_handler_t handler; void *user_data; } ply_terminal_active_vt_changed_closure_t; @@ -78,6 +84,7 @@ struct _ply_terminal int number_of_reopen_tries; ply_list_t *vt_change_closures; + ply_list_t *input_closures; ply_fd_watch_t *fd_watch; ply_terminal_color_t foreground_color; ply_terminal_color_t background_color; @@ -118,6 +125,7 @@ ply_terminal_new (const char *device_name) terminal->loop = ply_event_loop_get_default (); terminal->vt_change_closures = ply_list_new (); + terminal->input_closures = ply_list_new (); if (strncmp (device_name, "/dev/", strlen ("/dev/")) == 0) terminal->name = strdup (device_name); @@ -361,6 +369,28 @@ ply_terminal_reopen_device (ply_terminal_t *terminal) } static void +on_tty_input (ply_terminal_t *terminal) +{ + + ply_list_node_t *node; + + node = ply_list_get_first_node (terminal->input_closures); + while (node != NULL) + { + ply_terminal_input_closure_t *closure; + ply_list_node_t *next_node; + + closure = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (terminal->input_closures, node); + + if (closure->handler != NULL) + closure->handler (closure->user_data, terminal); + + node = next_node; + } +} + +static void on_tty_disconnected (ply_terminal_t *terminal) { ply_trace ("tty disconnected (fd %d)", terminal->fd); @@ -559,10 +589,10 @@ ply_terminal_open_device (ply_terminal_t *terminal) } terminal->fd_watch = ply_event_loop_watch_fd (terminal->loop, terminal->fd, - PLY_EVENT_LOOP_FD_STATUS_NONE, - (ply_event_handler_t) NULL, - (ply_event_handler_t) on_tty_disconnected, - terminal); + PLY_EVENT_LOOP_FD_STATUS_HAS_DATA, + (ply_event_handler_t) on_tty_input, + (ply_event_handler_t) on_tty_disconnected, + terminal); ply_terminal_check_for_vt (terminal); @@ -805,6 +835,26 @@ free_vt_change_closures (ply_terminal_t *terminal) ply_list_free (terminal->vt_change_closures); } +static void +free_input_closures (ply_terminal_t *terminal) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (terminal->input_closures); + while (node != NULL) + { + ply_terminal_input_closure_t *closure; + ply_list_node_t *next_node; + + closure = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (terminal->input_closures, node); + + free (closure); + node = next_node; + } + ply_list_free (terminal->input_closures); +} + void ply_terminal_free (ply_terminal_t *terminal) { @@ -830,6 +880,7 @@ ply_terminal_free (ply_terminal_t *terminal) ply_terminal_close (terminal); free_vt_change_closures (terminal); + free_input_closures (terminal); free (terminal->name); free (terminal); } @@ -1001,4 +1052,45 @@ ply_terminal_stop_watching_for_active_vt_change (ply_terminal_t *terminal, } } +void +ply_terminal_watch_for_input (ply_terminal_t *terminal, + ply_terminal_input_handler_t input_handler, + void *user_data) +{ + ply_terminal_input_closure_t *closure; + + closure = calloc (1, sizeof (*closure)); + closure->handler = input_handler; + closure->user_data = user_data; + + ply_list_append_data (terminal->input_closures, closure); +} + +void +ply_terminal_stop_watching_for_input (ply_terminal_t *terminal, + ply_terminal_input_handler_t input_handler, + void *user_data) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (terminal->input_closures); + while (node != NULL) + { + ply_terminal_input_closure_t *closure; + ply_list_node_t *next_node; + + closure = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (terminal->input_closures, node); + + if (closure->handler == input_handler && + closure->user_data == user_data) + { + free (closure); + ply_list_remove_node (terminal->input_closures, node); + } + + node = next_node; + } +} + /* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */ diff --git a/src/libply-splash-core/ply-terminal.h b/src/libply-splash-core/ply-terminal.h index 2eb9950..8b4b017 100644 --- a/src/libply-splash-core/ply-terminal.h +++ b/src/libply-splash-core/ply-terminal.h @@ -33,7 +33,8 @@ typedef struct _ply_terminal ply_terminal_t; typedef void (* ply_terminal_active_vt_changed_handler_t) (void *user_data, ply_terminal_t *terminal); - +typedef void (* ply_terminal_input_handler_t) (void *user_data, + ply_terminal_t *terminal); typedef enum { PLY_TERMINAL_COLOR_BLACK = 0, @@ -104,6 +105,13 @@ void ply_terminal_stop_watching_for_active_vt_change (ply_terminal_t *terminal, ply_terminal_active_vt_changed_handler_t active_vt_changed_handler, void *user_data); +void ply_terminal_watch_for_input (ply_terminal_t *terminal, + ply_terminal_input_handler_t input_handler, + void *user_data); +void ply_terminal_stop_watching_for_input (ply_terminal_t *terminal, + ply_terminal_input_handler_t input_handler, + void *user_data); + #endif #endif /* PLY_TERMINAL_H */ -- 1.7.5