summaryrefslogtreecommitdiffstats
path: root/lldb/source
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source')
-rw-r--r--lldb/source/Host/common/Editline.cpp10
-rw-r--r--lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp99
-rw-r--r--lldb/source/Host/posix/PipePosix.cpp162
-rw-r--r--lldb/source/Target/Process.cpp26
-rw-r--r--lldb/source/Utility/CMakeLists.txt1
-rw-r--r--lldb/source/Utility/SelectHelper.cpp294
6 files changed, 383 insertions, 209 deletions
diff --git a/lldb/source/Host/common/Editline.cpp b/lldb/source/Host/common/Editline.cpp
index 133a9a76dd9..d23a481d168 100644
--- a/lldb/source/Host/common/Editline.cpp
+++ b/lldb/source/Host/common/Editline.cpp
@@ -20,6 +20,7 @@
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Utility/LLDBAssert.h"
+#include "lldb/Utility/SelectHelper.h"
using namespace lldb_private;
using namespace lldb_private::line_editor;
@@ -155,11 +156,10 @@ IsInputPending (FILE * file)
// instead use some kind of yet-to-be-created abstraction that select-like functionality on
// non-socket objects.
const int fd = fileno (file);
- fd_set fds;
- FD_ZERO (&fds);
- FD_SET (fd, &fds);
- timeval timeout = { 0, 0 };
- return select (fd + 1, &fds, NULL, NULL, &timeout);
+ SelectHelper select_helper;
+ select_helper.SetTimeout(std::chrono::microseconds(0));
+ select_helper.FDSetRead(fd);
+ return select_helper.Select().Success();
}
namespace lldb_private
diff --git a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp
index 5d6a8938e00..a6d0958c8c6 100644
--- a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp
+++ b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp
@@ -20,6 +20,7 @@
#include "lldb/Host/SocketAddress.h"
#include "lldb/Host/Socket.h"
#include "lldb/Host/StringConvert.h"
+#include "lldb/Utility/SelectHelper.h"
// C Includes
#include <errno.h>
@@ -572,7 +573,7 @@ ConnectionFileDescriptor::GetURI()
return m_uri;
}
-// This ConnectionFileDescriptor::BytesAvailable() uses select().
+// This ConnectionFileDescriptor::BytesAvailable() uses select() via SelectHelper
//
// PROS:
// - select is consistent across most unix platforms
@@ -586,11 +587,6 @@ ConnectionFileDescriptor::GetURI()
// be used or a new version of ConnectionFileDescriptor::BytesAvailable()
// should be written for the system that is running into the limitations.
-#if defined(__APPLE__)
-#define FD_SET_DATA(fds) fds.data()
-#else
-#define FD_SET_DATA(fds) &fds
-#endif
ConnectionStatus
ConnectionFileDescriptor::BytesAvailable(uint32_t timeout_usec, Error *error_ptr)
@@ -602,21 +598,6 @@ ConnectionFileDescriptor::BytesAvailable(uint32_t timeout_usec, Error *error_ptr
if (log)
log->Printf("%p ConnectionFileDescriptor::BytesAvailable (timeout_usec = %u)", static_cast<void *>(this), timeout_usec);
- struct timeval *tv_ptr;
- struct timeval tv;
- if (timeout_usec == UINT32_MAX)
- {
- // Infinite wait...
- tv_ptr = nullptr;
- }
- else
- {
- TimeValue time_value;
- time_value.OffsetWithMicroSeconds(timeout_usec);
- tv.tv_sec = time_value.seconds();
- tv.tv_usec = time_value.microseconds();
- tv_ptr = &tv;
- }
// Make a copy of the file descriptors to make sure we don't
// have another thread change these values out from under us
@@ -624,8 +605,14 @@ ConnectionFileDescriptor::BytesAvailable(uint32_t timeout_usec, Error *error_ptr
const IOObject::WaitableHandle handle = m_read_sp->GetWaitableHandle();
const int pipe_fd = m_pipe.GetReadFileDescriptor();
+
if (handle != IOObject::kInvalidHandleValue)
{
+ SelectHelper select_helper;
+ if (timeout_usec != UINT32_MAX)
+ select_helper.SetTimeout(std::chrono::microseconds(timeout_usec));
+
+ select_helper.FDSetRead(handle);
#if defined(_MSC_VER)
// select() won't accept pipes on Windows. The entire Windows codepath needs to be
// converted over to using WaitForMultipleObjects and event HANDLEs, but for now at least
@@ -633,62 +620,14 @@ ConnectionFileDescriptor::BytesAvailable(uint32_t timeout_usec, Error *error_ptr
const bool have_pipe_fd = false;
#else
const bool have_pipe_fd = pipe_fd >= 0;
-#if !defined(__APPLE__)
- assert(handle < FD_SETSIZE);
- if (have_pipe_fd)
- assert(pipe_fd < FD_SETSIZE);
-#endif
#endif
+ if (have_pipe_fd)
+ select_helper.FDSetRead(pipe_fd);
+
while (handle == m_read_sp->GetWaitableHandle())
{
- const int nfds = std::max<int>(handle, pipe_fd) + 1;
-#if defined(__APPLE__)
- llvm::SmallVector<fd_set, 1> read_fds;
- read_fds.resize((nfds / FD_SETSIZE) + 1);
- for (size_t i = 0; i < read_fds.size(); ++i)
- FD_ZERO(&read_fds[i]);
-// FD_SET doesn't bounds check, it just happily walks off the end
-// but we have taken care of making the extra storage with our
-// SmallVector of fd_set objects
-#else
- fd_set read_fds;
- FD_ZERO(&read_fds);
-#endif
- FD_SET(handle, FD_SET_DATA(read_fds));
- if (have_pipe_fd)
- FD_SET(pipe_fd, FD_SET_DATA(read_fds));
- Error error;
-
- if (log)
- {
- if (have_pipe_fd)
- log->Printf(
- "%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds=%i, fds={%i, %i}, NULL, NULL, timeout=%p)...",
- static_cast<void *>(this), nfds, handle, pipe_fd, static_cast<void *>(tv_ptr));
- else
- log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds=%i, fds={%i}, NULL, NULL, timeout=%p)...",
- static_cast<void *>(this), nfds, handle, static_cast<void *>(tv_ptr));
- }
-
- const int num_set_fds = ::select(nfds, FD_SET_DATA(read_fds), NULL, NULL, tv_ptr);
- if (num_set_fds < 0)
- error.SetErrorToErrno();
- else
- error.Clear();
-
- if (log)
- {
- if (have_pipe_fd)
- log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds=%i, fds={%i, %i}, NULL, NULL, timeout=%p) "
- "=> %d, error = %s",
- static_cast<void *>(this), nfds, handle, pipe_fd, static_cast<void *>(tv_ptr), num_set_fds,
- error.AsCString());
- else
- log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds=%i, fds={%i}, NULL, NULL, timeout=%p) => "
- "%d, error = %s",
- static_cast<void *>(this), nfds, handle, static_cast<void *>(tv_ptr), num_set_fds, error.AsCString());
- }
+ Error error = select_helper.Select();
if (error_ptr)
*error_ptr = error;
@@ -704,6 +643,9 @@ ConnectionFileDescriptor::BytesAvailable(uint32_t timeout_usec, Error *error_ptr
default: // Other unknown error
return eConnectionStatusError;
+ case ETIMEDOUT:
+ return eConnectionStatusTimedOut;
+
case EAGAIN: // The kernel was (perhaps temporarily) unable to
// allocate the requested number of file descriptors,
// or we have non-blocking IO
@@ -713,15 +655,12 @@ ConnectionFileDescriptor::BytesAvailable(uint32_t timeout_usec, Error *error_ptr
break; // Lets keep reading to until we timeout
}
}
- else if (num_set_fds == 0)
- {
- return eConnectionStatusTimedOut;
- }
- else if (num_set_fds > 0)
+ else
{
- if (FD_ISSET(handle, FD_SET_DATA(read_fds)))
+ if (select_helper.FDIsSetRead(handle))
return eConnectionStatusSuccess;
- if (have_pipe_fd && FD_ISSET(pipe_fd, FD_SET_DATA(read_fds)))
+
+ if (select_helper.FDIsSetRead(pipe_fd))
{
// There is an interrupt or exit command in the command pipe
// Read the data from that pipe:
diff --git a/lldb/source/Host/posix/PipePosix.cpp b/lldb/source/Host/posix/PipePosix.cpp
index 353faae1628..6695bbfbac7 100644
--- a/lldb/source/Host/posix/PipePosix.cpp
+++ b/lldb/source/Host/posix/PipePosix.cpp
@@ -10,6 +10,7 @@
#include "lldb/Host/posix/PipePosix.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
+#include "lldb/Utility/SelectHelper.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/FileSystem.h"
@@ -65,73 +66,6 @@ Now()
return std::chrono::steady_clock::now();
}
-Error
-SelectIO(int handle, bool is_read, const std::function<Error(bool&)> &io_handler, const std::chrono::microseconds &timeout)
-{
- Error error;
- fd_set fds;
- bool done = false;
-
- using namespace std::chrono;
-
- const auto finish_time = Now() + timeout;
-
- while (!done)
- {
- struct timeval tv = {0, 0};
- if (timeout != microseconds::zero())
- {
- const auto remaining_dur = duration_cast<microseconds>(finish_time - Now());
- if (remaining_dur.count() <= 0)
- {
- error.SetErrorString("timeout exceeded");
- break;
- }
- const auto dur_secs = duration_cast<seconds>(remaining_dur);
- const auto dur_usecs = remaining_dur % seconds(1);
-
- tv.tv_sec = dur_secs.count();
- tv.tv_usec = dur_usecs.count();
- }
- else
- tv.tv_sec = 1;
-
- FD_ZERO(&fds);
- FD_SET(handle, &fds);
-
- const auto retval = ::select(handle + 1,
- (is_read) ? &fds : nullptr,
- (is_read) ? nullptr : &fds,
- nullptr, &tv);
- if (retval == -1)
- {
- if (errno == EINTR)
- continue;
- error.SetErrorToErrno();
- break;
- }
- if (retval == 0)
- {
- error.SetErrorString("timeout exceeded");
- break;
- }
- if (!FD_ISSET(handle, &fds))
- {
- error.SetErrorString("invalid state");
- break;
- }
-
- error = io_handler(done);
- if (error.Fail())
- {
- if (error.GetError() == EINTR)
- continue;
- break;
- }
- }
- return error;
-}
-
}
PipePosix::PipePosix()
@@ -383,27 +317,33 @@ PipePosix::ReadWithTimeout(void *buf, size_t size, const std::chrono::microsecon
if (!CanRead())
return Error(EINVAL, eErrorTypePOSIX);
- auto handle = GetReadFileDescriptor();
- return SelectIO(handle,
- true,
- [=, &bytes_read](bool &done)
- {
- Error error;
- auto result = ::read(handle,
- reinterpret_cast<char*>(buf) + bytes_read,
- size - bytes_read);
- if (result != -1)
- {
- bytes_read += result;
- if (bytes_read == size || result == 0)
- done = true;
- }
- else
- error.SetErrorToErrno();
-
- return error;
- },
- timeout);
+ const int fd = GetReadFileDescriptor();
+
+ SelectHelper select_helper;
+ select_helper.SetTimeout(timeout);
+ select_helper.FDSetRead(fd);
+
+ Error error;
+ while (error.Success())
+ {
+ error = select_helper.Select();
+ if (error.Success())
+ {
+ auto result = ::read(fd, reinterpret_cast<char*>(buf) + bytes_read, size - bytes_read);
+ if (result != -1)
+ {
+ bytes_read += result;
+ if (bytes_read == size || result == 0)
+ break;
+ }
+ else
+ {
+ error.SetErrorToErrno();
+ break;
+ }
+ }
+ }
+ return error;
}
Error
@@ -413,25 +353,29 @@ PipePosix::Write(const void *buf, size_t size, size_t &bytes_written)
if (!CanWrite())
return Error(EINVAL, eErrorTypePOSIX);
- auto handle = GetWriteFileDescriptor();
- return SelectIO(handle,
- false,
- [=, &bytes_written](bool &done)
- {
- Error error;
- auto result = ::write(handle,
- reinterpret_cast<const char*>(buf) + bytes_written,
- size - bytes_written);
- if (result != -1)
- {
- bytes_written += result;
- if (bytes_written == size)
- done = true;
- }
- else
- error.SetErrorToErrno();
-
- return error;
- },
- std::chrono::microseconds::zero());
+ const int fd = GetWriteFileDescriptor();
+ SelectHelper select_helper;
+ select_helper.SetTimeout(std::chrono::seconds(0));
+ select_helper.FDSetWrite(fd);
+
+ Error error;
+ while (error.Success())
+ {
+ error = select_helper.Select();
+ if (error.Success())
+ {
+ auto result = ::write(fd, reinterpret_cast<const char*>(buf) + bytes_written, size - bytes_written);
+ if (result != -1)
+ {
+ bytes_written += result;
+ if (bytes_written == size)
+ break;
+ }
+ else
+ {
+ error.SetErrorToErrno();
+ }
+ }
+ }
+ return error;
}
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 98f9ea13129..94e4f961064 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -62,6 +62,7 @@
#include "lldb/Target/ThreadPlanBase.h"
#include "lldb/Target/UnixSignals.h"
#include "lldb/Utility/NameMatches.h"
+#include "lldb/Utility/SelectHelper.h"
using namespace lldb;
using namespace lldb_private;
@@ -4925,25 +4926,20 @@ public:
m_is_running = true;
while (!GetIsDone())
{
- fd_set read_fdset;
- FD_ZERO (&read_fdset);
- FD_SET (read_fd, &read_fdset);
- FD_SET (pipe_read_fd, &read_fdset);
- const int nfds = std::max<int>(read_fd, pipe_read_fd) + 1;
- int num_set_fds = select(nfds, &read_fdset, nullptr, nullptr, nullptr);
-
- if (num_set_fds < 0)
- {
- const int select_errno = errno;
+ SelectHelper select_helper;
+ select_helper.FDSetRead(read_fd);
+ select_helper.FDSetRead(pipe_read_fd);
+ Error error = select_helper.Select();
- if (select_errno != EINTR)
- SetIsDone(true);
+ if (error.Fail())
+ {
+ SetIsDone(true);
}
- else if (num_set_fds > 0)
+ else
{
char ch = 0;
size_t n;
- if (FD_ISSET (read_fd, &read_fdset))
+ if (select_helper.FDIsSetRead(read_fd))
{
n = 1;
if (m_read_file.Read(&ch, n).Success() && n == 1)
@@ -4954,7 +4950,7 @@ public:
else
SetIsDone(true);
}
- if (FD_ISSET (pipe_read_fd, &read_fdset))
+ if (select_helper.FDIsSetRead(pipe_read_fd))
{
size_t bytes_read;
// Consume the interrupt byte
diff --git a/lldb/source/Utility/CMakeLists.txt b/lldb/source/Utility/CMakeLists.txt
index aa4ad030135..90aff225fe3 100644
--- a/lldb/source/Utility/CMakeLists.txt
+++ b/lldb/source/Utility/CMakeLists.txt
@@ -10,6 +10,7 @@ add_lldb_library(lldbUtility
PseudoTerminal.cpp
Range.cpp
RegisterNumber.cpp
+ SelectHelper.cpp
SharingPtr.cpp
StringExtractor.cpp
StringExtractorGDBRemote.cpp
diff --git a/lldb/source/Utility/SelectHelper.cpp b/lldb/source/Utility/SelectHelper.cpp
new file mode 100644
index 00000000000..7d616d5745a
--- /dev/null
+++ b/lldb/source/Utility/SelectHelper.cpp
@@ -0,0 +1,294 @@
+//===-- SelectHelper.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__APPLE__)
+// Enable this special support for Apple builds where we can have unlimited
+// select bounds. We tried switching to poll() and kqueue and we were panicing
+// the kernel, so we have to stick with select for now.
+#define _DARWIN_UNLIMITED_SELECT
+#endif
+
+// C Includes
+#include <errno.h>
+#if defined(_WIN32)
+// Define NOMINMAX to avoid macros that conflict with std::min and std::max
+#define NOMINMAX
+#include <winsock2.h>
+#else
+#include <sys/select.h>
+#endif
+
+// C++ Includes
+#include <algorithm>
+
+// Other libraries and framework includes
+#include "llvm/ADT/SmallVector.h"
+
+// Project includes
+#include "lldb/Core/Error.h"
+#include "lldb/Utility/SelectHelper.h"
+#include "lldb/Utility/LLDBAssert.h"
+
+SelectHelper::SelectHelper() :
+ m_fd_map(),
+ m_end_time() // Infinite timeout unless SelectHelper::SetTimeout() gets called
+{
+}
+
+void
+SelectHelper::SetTimeout(const std::chrono::microseconds &timeout)
+{
+ using namespace std::chrono;
+ m_end_time = steady_clock::time_point(steady_clock::now() + timeout);
+}
+
+void
+SelectHelper::FDSetRead(int fd)
+{
+ m_fd_map[fd].read_set = true;
+}
+
+void
+SelectHelper::FDSetWrite(int fd)
+{
+ m_fd_map[fd].write_set = true;
+}
+
+void
+SelectHelper::FDSetError(int fd)
+{
+ m_fd_map[fd].error_set = true;
+}
+
+bool
+SelectHelper::FDIsSetRead(int fd) const
+{
+ auto pos = m_fd_map.find(fd);
+ if (pos != m_fd_map.end())
+ return pos->second.read_is_set;
+ else
+ return false;
+}
+
+bool
+SelectHelper::FDIsSetWrite(int fd) const
+{
+ auto pos = m_fd_map.find(fd);
+ if (pos != m_fd_map.end())
+ return pos->second.write_is_set;
+ else
+ return false;
+}
+
+bool
+SelectHelper::FDIsSetError(int fd) const
+{
+ auto pos = m_fd_map.find(fd);
+ if (pos != m_fd_map.end())
+ return pos->second.error_is_set;
+ else
+ return false;
+}
+
+lldb_private::Error
+SelectHelper::Select()
+{
+ lldb_private::Error error;
+
+ int max_read_fd = -1;
+ int max_write_fd = -1;
+ int max_error_fd = -1;
+ int max_fd = -1;
+ for (auto &pair : m_fd_map)
+ {
+ pair.second.PrepareForSelect();
+ const int fd = pair.first;
+#if !defined(__APPLE__)
+ lldbassert(fd < FD_SETSIZE);
+ if (fd >= FD_SETSIZE)
+ {
+ error.SetErrorStringWithFormat("%i is too large for select()", fd);
+ return error;
+ }
+#endif
+ if (pair.second.read_set)
+ {
+ max_read_fd = std::max<int>(fd, max_read_fd);
+ max_fd = std::max<int>(fd, max_fd);
+ }
+ if (pair.second.write_set)
+ {
+ max_write_fd = std::max<int>(fd, max_write_fd);
+ max_fd = std::max<int>(fd, max_fd);
+ }
+ if (pair.second.error_set)
+ {
+ max_error_fd = std::max<int>(fd, max_error_fd);
+ max_fd = std::max<int>(fd, max_fd);
+ }
+ }
+
+ if (max_fd == -1)
+ {
+ error.SetErrorString("no valid file descriptors");
+ return error;
+ }
+
+ const int nfds = max_fd + 1;
+ fd_set *read_fdset_ptr = nullptr;
+ fd_set *write_fdset_ptr = nullptr;
+ fd_set *error_fdset_ptr = nullptr;
+ //----------------------------------------------------------------------
+ // Initialize and zero out the fdsets
+ //----------------------------------------------------------------------
+#if defined(__APPLE__)
+ llvm::SmallVector<fd_set, 1> read_fdset;
+ llvm::SmallVector<fd_set, 1> write_fdset;
+ llvm::SmallVector<fd_set, 1> error_fdset;
+
+ if (max_read_fd >= 0)
+ {
+ read_fdset.resize((nfds / FD_SETSIZE) + 1);
+ read_fdset_ptr = read_fdset.data();
+ }
+ if (max_write_fd >= 0)
+ {
+ write_fdset.resize((nfds / FD_SETSIZE) + 1);
+ write_fdset_ptr = write_fdset.data();
+ }
+ if (max_error_fd >= 0)
+ {
+ error_fdset.resize((nfds / FD_SETSIZE) + 1);
+ error_fdset_ptr = error_fdset.data();
+ }
+ for (auto &fd_set : read_fdset)
+ FD_ZERO(&fd_set);
+ for (auto &fd_set : write_fdset)
+ FD_ZERO(&fd_set);
+ for (auto &fd_set : error_fdset)
+ FD_ZERO(&fd_set);
+#else
+ fd_set read_fdset;
+ fd_set write_fdset;
+ fd_set error_fdset;
+
+ if (max_read_fd >= 0)
+ {
+ FD_ZERO(&read_fdset);
+ read_fdset_ptr = &read_fdset;
+ }
+ if (max_write_fd >= 0)
+ {
+ FD_ZERO(&write_fdset);
+ write_fdset_ptr = &write_fdset;
+ }
+ if (max_error_fd >= 0)
+ {
+ FD_ZERO(&error_fdset);
+ error_fdset_ptr = &error_fdset;
+ }
+#endif
+ //----------------------------------------------------------------------
+ // Set the FD bits in the fdsets for read/write/error
+ //----------------------------------------------------------------------
+ for (auto &pair : m_fd_map)
+ {
+ const int fd = pair.first;
+
+ if (pair.second.read_set)
+ FD_SET(fd, read_fdset_ptr);
+
+ if (pair.second.write_set)
+ FD_SET(fd, write_fdset_ptr);
+
+ if (pair.second.error_set)
+ FD_SET(fd, error_fdset_ptr);
+ }
+
+ //----------------------------------------------------------------------
+ // Setup our timeout time value if needed
+ //----------------------------------------------------------------------
+ struct timeval *tv_ptr = nullptr;
+ struct timeval tv = {0, 0};
+
+ while (1)
+ {
+ using namespace std::chrono;
+ //------------------------------------------------------------------
+ // Setup out relative timeout based on the end time if we have one
+ //------------------------------------------------------------------
+ if (m_end_time.hasValue())
+ {
+ tv_ptr = &tv;
+ const auto remaining_dur = duration_cast<microseconds>(m_end_time.getValue() - steady_clock::now());
+ if (remaining_dur.count() > 0)
+ {
+ // Wait for a specific amount of time
+ const auto dur_secs = duration_cast<seconds>(remaining_dur);
+ const auto dur_usecs = remaining_dur % seconds(1);
+ tv.tv_sec = dur_secs.count();
+ tv.tv_usec = dur_usecs.count();
+ }
+ else
+ {
+ // Just poll once with no timeout
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ }
+ }
+ const int num_set_fds = ::select(nfds, read_fdset_ptr, write_fdset_ptr, error_fdset_ptr, tv_ptr);
+ if (num_set_fds < 0)
+ {
+ // We got an error
+ error.SetErrorToErrno();
+ if (error.GetError() == EINTR)
+ {
+ error.Clear();
+ continue; // Keep calling select if we get EINTR
+ }
+ else
+ return error;
+ }
+ else if (num_set_fds == 0)
+ {
+ // Timeout
+ error.SetError(ETIMEDOUT, lldb::eErrorTypePOSIX);
+ error.SetErrorString("timed out");
+ return error;
+ }
+ else
+ {
+ // One or more descriptors were set, update the FDInfo::select_is_set mask
+ // so users can ask the SelectHelper class so clients can call one of:
+
+ for (auto &pair : m_fd_map)
+ {
+ const int fd = pair.first;
+
+ if (pair.second.read_set)
+ {
+ if (FD_ISSET(fd, read_fdset_ptr))
+ pair.second.read_is_set = true;
+ }
+ if (pair.second.write_set)
+ {
+ if (FD_ISSET(fd, write_fdset_ptr))
+ pair.second.write_is_set = true;
+ }
+ if (pair.second.error_set)
+ {
+ if (FD_ISSET(fd, error_fdset_ptr))
+ pair.second.error_is_set = true;
+ }
+ }
+ break;
+ }
+ }
+ return error;
+}
OpenPOWER on IntegriCloud