libc: translate terminal user interrupts to SIGINT

Issue #3546
This commit is contained in:
Norman Feske 2019-10-30 21:19:11 +01:00 committed by Christian Helmuth
parent 23d21d77e9
commit c1012e6a45
2 changed files with 44 additions and 10 deletions

View File

@ -123,6 +123,11 @@ struct Libc::Kernel final : Vfs::Io_response_handler,
void _handle_terminal_resize(); void _handle_terminal_resize();
/* handler for watching user interrupts (control-c) */
Constructible<Watch_handler<Kernel>> _user_interrupt_handler { };
void _handle_user_interrupt();
Signal _signal; Signal _signal;
Reconstructible<Io_signal_handler<Kernel>> _resume_main_handler { Reconstructible<Io_signal_handler<Kernel>> _resume_main_handler {

View File

@ -169,22 +169,44 @@ void Libc::Kernel::_init_file_descriptors()
file_descriptor_allocator()->preserve(fd); 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 const * const stdout_fd =
file_descriptor_allocator()->find_by_libc_fd(STDOUT_FILENO); file_descriptor_allocator()->find_by_libc_fd(STDOUT_FILENO);
if (stdout_fd && stdout_fd->fd_path) { with_ioctl_path(stdout_fd, "info", [&] (Directory &root_dir, char const *path) {
Absolute_path dir = Vfs_plugin::ioctl_dir(*stdout_fd); _terminal_resize_handler.construct(root_dir, path, *this,
dir.append_element("info"); &Kernel::_handle_terminal_resize); });
_vfs.with_root_dir([&] (Directory &root_dir) { /*
if (root_dir.file_exists(dir.string())) * Watch stdin's 'interrupts' pseudo file to detect control-c events
_terminal_resize_handler.construct(root_dir, dir.string(), */
*this, &Kernel::_handle_terminal_resize); 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() void Libc::Kernel::_clone_state_from_parent()
{ {
struct Range { void *at; size_t size; }; struct Range { void *at; size_t size; };