From 93e6efc00153e625e4ceb8a51e01b324247d312a Mon Sep 17 00:00:00 2001 From: Martin Lund Date: Thu, 24 Nov 2022 22:52:28 +0100 Subject: [PATCH] Add threaded input handling To make tio more responsive to quit and I/O flush key command when main I/O thread is blocked on output. --- man/tio.1.in | 2 + src/main.c | 6 +++ src/meson.build | 5 ++- src/tty.c | 117 ++++++++++++++++++++++++++++++++++++++++++++---- src/tty.h | 2 + 5 files changed, 123 insertions(+), 9 deletions(-) diff --git a/man/tio.1.in b/man/tio.1.in index 87cd9ef..3f29c6b 100644 --- a/man/tio.1.in +++ b/man/tio.1.in @@ -291,6 +291,8 @@ Show configuration (baudrate, databits, etc.) Toggle local echo mode .IP "\fBctrl-t f" Toggle log to file +.IP "\fBctrl-t F" +Flush data I/O channels (discard data written but not transmitted and data received but not read) .IP "\fBctrl-t g" Toggle serial port line .IP "\fBctrl-t h" diff --git a/src/main.c b/src/main.c index d2b1c0d..ddf8848 100644 --- a/src/main.c +++ b/src/main.c @@ -120,6 +120,12 @@ int main(int argc, char *argv[]) socket_configure(); } + /* Spawn input handling into separate thread */ + tty_input_thread_create(); + + /* Wait for input to be ready */ + tty_input_thread_wait_ready(); + /* Connect to tty device */ if (option.no_autoconnect) { diff --git a/src/meson.build b/src/meson.build index 0077733..cec9429 100644 --- a/src/meson.build +++ b/src/meson.build @@ -20,9 +20,12 @@ tio_sources = [ 'alert.c' ] -tio_dep = dependency('inih', required: true, +tio_dep = [ + dependency('threads', required: true), + dependency('inih', required: true, fallback : ['libinih', 'inih_dep'], default_options: ['default_library=static', 'distro_install=false']) +] tio_c_args = ['-Wno-unused-result'] diff --git a/src/tty.c b/src/tty.c index 328be11..83116b9 100644 --- a/src/tty.c +++ b/src/tty.c @@ -40,6 +40,7 @@ #include #include #include +#include #include "config.h" #include "configfile.h" #include "tty.h" @@ -81,6 +82,7 @@ #define KEY_C 0x63 #define KEY_E 0x65 #define KEY_F 0x66 +#define KEY_SHIFT_F 0x46 #define KEY_G 0x67 #define KEY_H 0x68 #define KEY_L 0x6C @@ -134,6 +136,9 @@ static unsigned char hex_char_index = 0; static char tty_buffer[BUFSIZ*2]; static size_t tty_buffer_count = 0; static char *tty_buffer_write_ptr = tty_buffer; +static pthread_t thread; +static int pipefd[2]; +static pthread_mutex_t mutex_input_ready = PTHREAD_MUTEX_INITIALIZER; static void optional_local_echo(char c) { @@ -256,6 +261,99 @@ ssize_t tty_write(int fd, const void *buffer, size_t count) return bytes_written; } +void *tty_stdin_input_thread(void *arg) +{ + UNUSED(arg); + char input_buffer[BUFSIZ]; + ssize_t byte_count; + ssize_t bytes_written; + + // Create FIFO pipe + if (pipe(pipefd) == -1) + { + tio_error_printf("Failed to create pipe"); + exit(EXIT_FAILURE); + } + + // Signal that input pipe is ready + pthread_mutex_unlock(&mutex_input_ready); + + // Input loop for stdin + while (1) + { + /* Input from stdin ready */ + byte_count = read(STDIN_FILENO, input_buffer, BUFSIZ); + if (byte_count < 0) + { + tio_warning_printf("Could not read from stdin (%s)", strerror(errno)); + } + else if (byte_count == 0) + { + // Close write end to signal EOF in read end + close(pipefd[1]); + pthread_exit(0); + } + + if (interactive_mode) + { + static char previous_char = 0; + char input_char; + + // Process quit and flush key command + for (int i = 0; i 0) { - if (FD_ISSET(STDIN_FILENO, &rdfs)) + if (FD_ISSET(pipefd[0], &rdfs)) { /* Input from stdin ready */ /* Read one character */ - status = read(STDIN_FILENO, &input_char, 1); + status = read(pipefd[0], &input_char, 1); if (status <= 0) { tio_error_printf("Could not read from stdin"); @@ -1200,9 +1301,9 @@ int tty_connect(void) FD_SET(fd, &rdfs); if (!ignore_stdin) { - FD_SET(STDIN_FILENO, &rdfs); + FD_SET(pipefd[0], &rdfs); } - maxfd = MAX(fd, STDIN_FILENO); + maxfd = MAX(fd, pipefd[0]); maxfd = MAX(maxfd, socket_add_fds(&rdfs, true)); /* Manage timeout */ @@ -1309,10 +1410,10 @@ int tty_connect(void) } } } - else if (FD_ISSET(STDIN_FILENO, &rdfs)) + else if (FD_ISSET(pipefd[0], &rdfs)) { /* Input from stdin ready */ - ssize_t bytes_read = read(STDIN_FILENO, input_buffer, BUFSIZ); + ssize_t bytes_read = read(pipefd[0], input_buffer, BUFSIZ); if (bytes_read < 0) { tio_error_printf_silent("Could not read from stdin (%s)", strerror(errno)); diff --git a/src/tty.h b/src/tty.h index 14d1779..c4b6797 100644 --- a/src/tty.h +++ b/src/tty.h @@ -31,3 +31,5 @@ void tty_configure(void); int tty_connect(void); void tty_wait_for_device(void); void list_serial_devices(void); +void tty_input_thread_create(void); +void tty_input_thread_wait_ready(void);