From 26011a715162a08f35fda71d6d916885d49344b4 Mon Sep 17 00:00:00 2001 From: Christian Helmuth Date: Mon, 28 Sep 2020 16:14:24 +0200 Subject: [PATCH] libc: update status for component select handlers In case of contexts blocked in select() the monitor updates the file-descriptor status, but if the entrypoint is just blocked for the select handler, the status must be updated explicitly on dispatch_select(). --- repos/libports/lib/symbols/libc | 1 - repos/libports/src/lib/libc/select.cc | 5 +- .../libports/src/test/libc_component/main.cc | 88 +++++++++++-------- 3 files changed, 54 insertions(+), 40 deletions(-) diff --git a/repos/libports/lib/symbols/libc b/repos/libports/lib/symbols/libc index 6f870603c9..abbc67796b 100644 --- a/repos/libports/lib/symbols/libc +++ b/repos/libports/lib/symbols/libc @@ -418,7 +418,6 @@ lcong48 T ldexp T ldiv T lfind T -libc_select_notify V link W listen T llabs T diff --git a/repos/libports/src/lib/libc/select.cc b/repos/libports/src/lib/libc/select.cc index a7c8c857c5..034ea6a32b 100644 --- a/repos/libports/src/lib/libc/select.cc +++ b/repos/libports/src/lib/libc/select.cc @@ -63,9 +63,6 @@ void Libc::init_select(Select &select, Signal &signal, Monitor &monitor) } -void (*libc_select_notify)() __attribute__((weak)); - - /** Description for a task waiting in select */ struct Libc::Select_cb { @@ -416,6 +413,8 @@ int Libc::Select_handler_base::select(int nfds, fd_set &readfds, void Libc::Select_handler_base::dispatch_select() { + Libc::select_notify_from_kernel(); + Select_handler_cb &select_cb = *_select_cb; if (select_cb->nready == 0) return; diff --git a/repos/libports/src/test/libc_component/main.cc b/repos/libports/src/test/libc_component/main.cc index 0cf66e8a6e..97766550a4 100644 --- a/repos/libports/src/test/libc_component/main.cc +++ b/repos/libports/src/test/libc_component/main.cc @@ -53,7 +53,7 @@ static void use_file_system() { int result = 0; - int const fd = open("/tmp/blub", O_RDWR | O_NONBLOCK | O_CREAT | O_APPEND); + int const fd = open("/tmp/blub", O_RDWR /*| O_NONBLOCK*/ | O_CREAT | O_APPEND); if (fd == -1) die("open"); printf("open returned fd %d\n", fd); @@ -96,41 +96,6 @@ struct Log::Session_component : Genode::Rpc_object fd_set _exceptfds; bool _in_read = false; - void _select() - { - int nready = 0; - do { - fd_set readfds = _readfds; - fd_set writefds = _writefds; - fd_set exceptfds = _exceptfds; - - nready = _select_handler.select(_fd + 1, readfds, writefds, exceptfds); - if (nready) - _select_ready(nready, readfds, writefds, exceptfds); - } while (nready); - } - - Libc::Select_handler _select_handler { - *this, &Session_component::_select_ready }; - - void _read() - { - _in_read = true; - - /* never mind the potentially nested with_libc */ - Libc::with_libc([&] () { - int const result = read(_fd, _buf, sizeof(_buf)-1); - if (result <= 0) { - Genode::warning("read returned ", result, " in select handler"); - return; - } - _buf[result] = 0; - Genode::log("read from file \"", Genode::Cstring(_buf), "\""); - }); - - _in_read = false; - } - void _select_ready(int nready, fd_set const &readfds, fd_set const &writefds, fd_set const &exceptfds) { Libc::with_libc([&] () { @@ -154,6 +119,55 @@ struct Log::Session_component : Genode::Rpc_object }); } + void _select() + { + /* + * This function activates the select handler. Ready file FDs must be + * handled immediately on return from select() as these events will not + * unblock the entrypoint later on. + */ + int nready = 0; + do { + fd_set readfds = _readfds; + fd_set writefds = _writefds; + fd_set exceptfds = _exceptfds; + + nready = _select_handler.select(_fd + 1, readfds, writefds, exceptfds); + if (nready) + _select_ready(nready, readfds, writefds, exceptfds); + } while (nready); + } + + Libc::Select_handler _select_handler { + *this, &Session_component::_handle_select }; + + void _handle_select(int nready, fd_set const &readfds, fd_set const &writefds, fd_set const &exceptfds) + { + /* handle all ready fds */ + _select_ready(nready, readfds, writefds, exceptfds); + + /* reactivate select handler */ + _select(); + } + + void _read() + { + _in_read = true; + + /* never mind the potentially nested with_libc */ + Libc::with_libc([&] () { + int const result = read(_fd, _buf, sizeof(_buf)-1); + if (result <= 0) { + Genode::warning("read returned ", result, " in select handler"); + return; + } + _buf[result] = 0; + Genode::log("read from file \"", Genode::Cstring(_buf), "\""); + }); + + _in_read = false; + } + Session_component(Libc::Env &env) : _env(env) { Libc::with_libc([&] () { @@ -171,6 +185,8 @@ struct Log::Session_component : Genode::Rpc_object /* initially call read two times to ensure blocking */ _read(); _read(); + + _select(); } void write(String const &string_buf) override