// Copyright (C) 2025 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h>
#include <exceptions/exceptions.h>
#include <util/select_event_handler.h>
#include <cstring>
#ifndef FD_COPY
#define FD_COPY(orig, copy) \
do { \
memcpy(copy, orig, sizeof(fd_set)); \
} while (0)
#endif
namespace isc {
namespace util {
SelectEventHandler::SelectEventHandler() : FDEventHandler(TYPE_SELECT), max_fd_(0) {<--- Member variable 'SelectEventHandler::read_fd_set_data_' is not initialized in the constructor. [+]Member variable 'SelectEventHandler::read_fd_set_data_' is not initialized in the constructor. Member variables of native types, pointers, or references are left uninitialized when the class is instantiated. That may cause bugs or undefined behavior.
clear();
}
void SelectEventHandler::add(int fd) {
if (fd < 0) {
isc_throw(BadValue, "invalid negative value for fd");
}
if (fd >= FD_SETSIZE) {
isc_throw(BadValue, "invalid value for fd exceeds maximum allowed " << FD_SETSIZE);
}
// Add this socket to read set
FD_SET(fd, &read_fd_set_);
if (fd > max_fd_) {
max_fd_ = fd;
}
}
int SelectEventHandler::waitEvent(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */,
bool use_timeout /* = true */) {
// Sanity check for microsecond timeout.
if (timeout_usec >= 1000000) {
isc_throw(BadValue, "fractional timeout must be shorter than"
" one million microseconds");
}
struct timeval select_timeout;
struct timeval* select_timeout_p = 0;
if (use_timeout) {
select_timeout.tv_sec = timeout_sec;
select_timeout.tv_usec = timeout_usec;
select_timeout_p = &select_timeout;
}
FD_COPY(&read_fd_set_, &read_fd_set_data_);
return (select(max_fd_ + 1, &read_fd_set_data_, 0, 0, select_timeout_p));
}
bool SelectEventHandler::readReady(int fd) {
if (fd < 0) {
isc_throw(BadValue, "invalid negative value for fd");
}
if (fd >= FD_SETSIZE) {
isc_throw(BadValue, "invalid value for fd exceeds maximum allowed " << FD_SETSIZE);
}
return (FD_ISSET(fd, &read_fd_set_data_));
}
bool SelectEventHandler::hasError(int fd) {
if (fd < 0) {
isc_throw(BadValue, "invalid negative value for fd");
}
if (fd >= FD_SETSIZE) {
isc_throw(BadValue, "invalid value for fd exceeds maximum allowed " << FD_SETSIZE);
}
return (false);
}
void SelectEventHandler::clear() {
FD_ZERO(&read_fd_set_);
max_fd_ = 0;
}
} // end of namespace isc::util
} // end of namespace isc