Noux: fix resetting wrong number of fds

Since the number of the fds in the select call is not necassarily equal
to the number of fds SYSCALL_SELECT returns we have to reset the number
of fds given as argument to select().

This keeps OpenSSH from reading from a non-ready socket.

Fixes #494.
This commit is contained in:
Josef Söntgen 2012-11-08 16:57:58 +01:00 committed by Norman Feske
parent a3c45412aa
commit 3c562d042d

View File

@ -237,7 +237,7 @@ static size_t marshal_fds(fd_set *src_fds, int nfds,
/**
* Unmarshal result of select syscall into fd set
*/
static void unmarshal_fds(int *src_fds, size_t src_fds_len, fd_set *dst_fds)
static void unmarshal_fds(int nfds, int *src_fds, size_t src_fds_len, fd_set *dst_fds)
{
if (!dst_fds) return;
@ -247,8 +247,13 @@ static void unmarshal_fds(int *src_fds, size_t src_fds_len, fd_set *dst_fds)
* it was allocated dynamically. So we will reset the fd_set manually which
* will work fine as long as we are using FreeBSDs libc - another libc however
* might use a different struct.
*
* Note: The fds are actually stored in a bit-array. So we need to calculate
* how many array entries we have to reset. sizeof (fd_mask) will return the
* size of one entry in bytes.
*/
for (size_t i = 0; i < src_fds_len; i++)
int _ = nfds / (sizeof (fd_mask) * 8) + 1;
for (int i = 0; i < _; i++)
dst_fds->__fds_bits[i] = 0;
for (size_t i = 0; i < src_fds_len; i++)
@ -329,19 +334,19 @@ extern "C" int select(int nfds, fd_set *readfds, fd_set *writefds,
int total_fds = 0;
if (readfds != NULL) {
unmarshal_fds(src, out_fds.num_rd, readfds);
unmarshal_fds(nfds, src, out_fds.num_rd, readfds);
src += out_fds.num_rd;
total_fds += out_fds.num_rd;
}
if (writefds != NULL) {
unmarshal_fds(src, out_fds.num_wr, writefds);
unmarshal_fds(nfds, src, out_fds.num_wr, writefds);
src += out_fds.num_wr;
total_fds += out_fds.num_wr;
}
if (exceptfds != NULL) {
unmarshal_fds(src, out_fds.num_ex, exceptfds);
unmarshal_fds(nfds, src, out_fds.num_ex, exceptfds);
/* exceptfds are currently ignored */
}