mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-24 15:56:41 +00:00
libc: cancel select when POSIX signal occurs
With this patch, Vim running via the 'bash.run' script becomes able to adopt itself to changed window dimensions. Issue #3544
This commit is contained in:
parent
fafa409cf9
commit
636e0f6444
@ -65,7 +65,7 @@ namespace Libc {
|
||||
/**
|
||||
* Select support
|
||||
*/
|
||||
void init_select(Suspend &, Resume &, Select &);
|
||||
void init_select(Suspend &, Resume &, Select &, Signal &);
|
||||
|
||||
/**
|
||||
* Support for querying available RAM quota in sysctl functions
|
||||
|
@ -347,7 +347,7 @@ Libc::Kernel::Kernel(Genode::Env &env, Genode::Allocator &heap)
|
||||
init_sleep(*this);
|
||||
init_vfs_plugin(*this);
|
||||
init_time(*this, _rtc_path, *this);
|
||||
init_select(*this, *this, *this);
|
||||
init_select(*this, *this, *this, _signal);
|
||||
init_socket_fs(*this);
|
||||
init_passwd(_passwd_config());
|
||||
init_signal(_signal);
|
||||
|
@ -36,9 +36,11 @@
|
||||
|
||||
/* libc-internal includes */
|
||||
#include <internal/init.h>
|
||||
#include <internal/signal.h>
|
||||
#include <internal/suspend.h>
|
||||
#include <internal/resume.h>
|
||||
#include <internal/select.h>
|
||||
#include <internal/errno.h>
|
||||
|
||||
namespace Libc {
|
||||
struct Select_cb;
|
||||
@ -51,13 +53,16 @@ using namespace Libc;
|
||||
static Suspend *_suspend_ptr;
|
||||
static Resume *_resume_ptr;
|
||||
static Select *_select_ptr;
|
||||
static Libc::Signal *_signal_ptr;
|
||||
|
||||
|
||||
void Libc::init_select(Suspend &suspend, Resume &resume, Select &select)
|
||||
void Libc::init_select(Suspend &suspend, Resume &resume, Select &select,
|
||||
Signal &signal)
|
||||
{
|
||||
_suspend_ptr = &suspend;
|
||||
_resume_ptr = &resume;
|
||||
_select_ptr = &select;
|
||||
_signal_ptr = &signal;
|
||||
}
|
||||
|
||||
|
||||
@ -312,18 +317,38 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
||||
|
||||
{
|
||||
struct Missing_call_of_init_select : Exception { };
|
||||
if (!_suspend_ptr)
|
||||
if (!_suspend_ptr || !_signal_ptr)
|
||||
throw Missing_call_of_init_select();
|
||||
}
|
||||
|
||||
while (!timeout.expired() && select_cb->nready == 0)
|
||||
unsigned const orig_signal_count = _signal_ptr->count();
|
||||
|
||||
auto signal_occurred_during_select = [&] ()
|
||||
{
|
||||
return _signal_ptr->count() != orig_signal_count;
|
||||
};
|
||||
|
||||
for (;;) {
|
||||
if (timeout.expired())
|
||||
break;
|
||||
|
||||
if (select_cb->nready != 0)
|
||||
break;
|
||||
|
||||
if (signal_occurred_during_select())
|
||||
break;
|
||||
|
||||
timeout.duration = _suspend_ptr->suspend(check, timeout.duration);
|
||||
}
|
||||
|
||||
select_cb_list().remove(&(*select_cb));
|
||||
|
||||
if (timeout.expired())
|
||||
return 0;
|
||||
|
||||
if (signal_occurred_during_select())
|
||||
return Errno(EINTR);
|
||||
|
||||
/* not timed out -> results have been stored in select_cb by select_notify() */
|
||||
|
||||
if (readfds) *readfds = select_cb->readfds;
|
||||
|
Loading…
Reference in New Issue
Block a user