From c1012e6a45115c3422c71c6b109400fd7dc89c19 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Wed, 30 Oct 2019 21:19:11 +0100 Subject: [PATCH] libc: translate terminal user interrupts to SIGINT Issue #3546 --- repos/libports/src/lib/libc/internal/kernel.h | 5 ++ repos/libports/src/lib/libc/kernel.cc | 49 +++++++++++++++---- 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/repos/libports/src/lib/libc/internal/kernel.h b/repos/libports/src/lib/libc/internal/kernel.h index 107bc09f3..06cbeb6dc 100644 --- a/repos/libports/src/lib/libc/internal/kernel.h +++ b/repos/libports/src/lib/libc/internal/kernel.h @@ -123,6 +123,11 @@ struct Libc::Kernel final : Vfs::Io_response_handler, void _handle_terminal_resize(); + /* handler for watching user interrupts (control-c) */ + Constructible> _user_interrupt_handler { }; + + void _handle_user_interrupt(); + Signal _signal; Reconstructible> _resume_main_handler { diff --git a/repos/libports/src/lib/libc/kernel.cc b/repos/libports/src/lib/libc/kernel.cc index 2f30c33c6..fc4d36849 100644 --- a/repos/libports/src/lib/libc/kernel.cc +++ b/repos/libports/src/lib/libc/kernel.cc @@ -169,22 +169,44 @@ void Libc::Kernel::_init_file_descriptors() file_descriptor_allocator()->preserve(fd); } + /** + * Call 'fn' with root directory and path to ioctl pseudo file as arguments + * + * If no matching ioctl pseudo file exists, 'fn' is not called. + */ + auto with_ioctl_path = [&] (File_descriptor const *fd, char const *file, auto fn) + { + if (!fd || !fd->fd_path) + return; + + Absolute_path const ioctl_dir = Vfs_plugin::ioctl_dir(*fd); + Absolute_path path = ioctl_dir; + path.append_element(file); + + _vfs.with_root_dir([&] (Directory &root_dir) { + if (root_dir.file_exists(path.string())) + fn(root_dir, path.string()); }); + }; + /* - * Watch stdout's 'info' pseudo file to detect terminal resize events + * Watch stdout's 'info' pseudo file to detect terminal-resize events */ File_descriptor const * const stdout_fd = file_descriptor_allocator()->find_by_libc_fd(STDOUT_FILENO); - if (stdout_fd && stdout_fd->fd_path) { - Absolute_path dir = Vfs_plugin::ioctl_dir(*stdout_fd); - dir.append_element("info"); + with_ioctl_path(stdout_fd, "info", [&] (Directory &root_dir, char const *path) { + _terminal_resize_handler.construct(root_dir, path, *this, + &Kernel::_handle_terminal_resize); }); - _vfs.with_root_dir([&] (Directory &root_dir) { - if (root_dir.file_exists(dir.string())) - _terminal_resize_handler.construct(root_dir, dir.string(), - *this, &Kernel::_handle_terminal_resize); - }); - } + /* + * Watch stdin's 'interrupts' pseudo file to detect control-c events + */ + File_descriptor const * const stdin_fd = + file_descriptor_allocator()->find_by_libc_fd(STDIN_FILENO); + + with_ioctl_path(stdin_fd, "interrupts", [&] (Directory &root_dir, char const *path) { + _user_interrupt_handler.construct(root_dir, path, + *this, &Kernel::_handle_user_interrupt); }); } @@ -195,6 +217,13 @@ void Libc::Kernel::_handle_terminal_resize() } +void Libc::Kernel::_handle_user_interrupt() +{ + _signal.charge(SIGINT); + _resume_main(); +} + + void Libc::Kernel::_clone_state_from_parent() { struct Range { void *at; size_t size; };