diff options
author | Tom de Vries <tdevries@suse.de> | 2024-11-22 12:54:57 +0100 |
---|---|---|
committer | Tom de Vries <tdevries@suse.de> | 2024-11-22 12:54:57 +0100 |
commit | dcc4d678668bac6e3887ea04ff2337996629411e (patch) | |
tree | d03d49f200707d4955bf582f0ce8c9e755fde91a | |
parent | ld/PE: Handle MS style import libraries for files named *.exe too (diff) | |
download | binutils-gdb-dcc4d678668bac6e3887ea04ff2337996629411e.tar.gz binutils-gdb-dcc4d678668bac6e3887ea04ff2337996629411e.tar.bz2 binutils-gdb-dcc4d678668bac6e3887ea04ff2337996629411e.zip |
[gdb] Add gdb_select variant for looping
In interruptible_select we run gdb_select in a loop:
...
do
{
res = gdb_select (n, readfds, writefds, exceptfds, timeout);
}
while (res == -1 && errno == EINTR);
...
but man select tells us that:
- if using select() within a loop, the sets (readfds, writefds and
exceptfds) must be reinitialized before each call, and
- timeout should be considered to be undefined after select() returns.
Add a gdb_select variant:
...
static int
gdb_select (int n,
const fd_set *req_readfds, fd_set *ret_readfds,
const fd_set *req_writefds, fd_set *ret_writefds,
const fd_set *req_exceptfds, fd_set *ret_exceptfds,
const struct timeval *req_timeout, struct timeval *ret_timeout)
...
that keeps requested and returned values separate, ensuring that the requested
values stay constant.
Tested on x86_64-linux.
Reviewed-By: Alexandra Petlanova Hajkova <ahajkova@redhat.com>
-rw-r--r-- | gdb/event-top.c | 86 |
1 files changed, 81 insertions, 5 deletions
diff --git a/gdb/event-top.c b/gdb/event-top.c index 38a59ba55a0..9c0087adb10 100644 --- a/gdb/event-top.c +++ b/gdb/event-top.c @@ -1268,6 +1268,60 @@ handle_sigint (int sig) mark_async_signal_handler (sigint_token); } +/* Copy file descriptors smaller than N from SRC to DST and return DST. + Portable version of FD_COPY. */ + +static fd_set * +fd_copy (fd_set *dst, const fd_set *src, int n) +{ + FD_ZERO (dst); + for (int i = 0; i < n; ++i) + if (FD_ISSET (i, src)) + FD_SET (i, dst); + + return dst; +} + +/* Copy SRC to DST and return DST. */ + +static struct timeval * +timeval_copy (struct timeval *dst, const struct timeval *src) +{ + *dst = *src; + return dst; +} + +/* Version of select that can be used in a loop, since unlike select it keeps + requested and returned values separate. */ + +static int +gdb_select (int n, + const fd_set *req_readfds, fd_set *ret_readfds, + const fd_set *req_writefds, fd_set *ret_writefds, + const fd_set *req_exceptfds, fd_set *ret_exceptfds, + const struct timeval *req_timeout, struct timeval *ret_timeout) +{ + ret_readfds + = (req_readfds == nullptr + ? nullptr + : fd_copy (ret_readfds, req_readfds, n)); + ret_writefds + = (req_writefds == nullptr + ? nullptr + : fd_copy (ret_writefds, req_writefds, n)); + ret_exceptfds + = (req_exceptfds == nullptr + ? nullptr + : fd_copy (ret_exceptfds, req_exceptfds, n)); + + ret_timeout + = (req_timeout == nullptr + ? nullptr + : timeval_copy (ret_timeout, req_timeout)); + + return gdb_select (n, ret_readfds, ret_writefds, ret_exceptfds, ret_timeout); +} + /* See gdb_select.h. */ int @@ -1290,11 +1344,33 @@ interruptible_select (int n, if (n <= fd) n = fd + 1; - do - { - res = gdb_select (n, readfds, writefds, exceptfds, timeout); - } - while (res == -1 && errno == EINTR); + { + fd_set ret_readfds, ret_writefds, ret_exceptfds; + struct timeval ret_timeout; + + while (true) + { + res = gdb_select (n, + readfds, &ret_readfds, + writefds, &ret_writefds, + exceptfds, &ret_exceptfds, + timeout, &ret_timeout); + + if (res == -1 && errno == EINTR) + continue; + + break; + } + + if (readfds != nullptr) + fd_copy (readfds, &ret_readfds, n); + if (writefds != nullptr) + fd_copy (writefds, &ret_writefds, n); + if (exceptfds != nullptr) + fd_copy (exceptfds, &ret_exceptfds, n); + if (timeout) + timeval_copy (timeout, &ret_timeout); + } if (res == 1 && FD_ISSET (fd, readfds)) { |