io_service_->post(std::bind(&HATest::signalServiceRunning, this, std::ref(running),
std::ref(mutex), std::ref(condvar)));
+ IfaceMgr::instance().setCheckThreadId(false);
+
auto f = [](IOServicePtr io_service) {
try {
io_service->run();
} catch (...) {
ADD_FAILURE() << "error while running IOService::run";
}
+ IfaceMgr::instance().setCheckThreadId(true);
};
boost::shared_ptr<std::thread>
IfaceMgr::IfaceMgr()
: packet_filter_(new PktFilterInet()),
packet_filter6_(new PktFilterInet6()),
- test_mode_(false), allow_loopback_(false) {
+ test_mode_(false), check_thread_id_(true), allow_loopback_(false) {
id_ = std::this_thread::get_id();
// Ensure that PQMs have been created to guarantee we have
isc_throw(BadValue, "Attempted to install callback for invalid socket "
<< socketfd);
}
- if (std::this_thread::get_id() != id_) {
+ if (check_thread_id_ && std::this_thread::get_id() != id_) {
LOG_ERROR(dhcp_logger, DHCP_ADD_EXTERNAL_SOCKET)
.arg(socketfd)
.arg(std::this_thread::get_id());
void
IfaceMgr::deleteExternalSocketInternal(int socketfd) {
- if (std::this_thread::get_id() != id_) {
+ if (check_thread_id_ && std::this_thread::get_id() != id_) {
LOG_ERROR(dhcp_logger, DHCP_DELETE_EXTERNAL_SOCKET)
.arg(socketfd)
.arg(std::this_thread::get_id());
void
IfaceMgr::deleteAllExternalSockets() {
- if (std::this_thread::get_id() != id_) {
+ if (check_thread_id_ && std::this_thread::get_id() != id_) {
LOG_ERROR(dhcp_logger, DHCP_DELETE_ALL_EXTERNAL_SOCKETS)
.arg(std::this_thread::get_id());
}
#include <boost/scoped_array.hpp>
#include <boost/shared_ptr.hpp>
+#include <atomic>
#include <functional>
#include <list>
#include <mutex>
return (test_mode_);
}
+ /// @brief Get the flag which indicates if thread ID is checked when
+ /// performing operations with external sockets.
+ ///
+ /// @return true if the @c IfaceMgr checks thread ID, false otherwise.
+ bool getCheckThreadId() const {
+ return (check_thread_id_);
+ }
+
+ /// @brief Set the flag which indicates if thread ID is checked when
+ /// performing operations with external sockets.
+ ///
+ /// @param check A flag which indicates if thread ID is checked when
+ /// performing operations with external sockets.
+ void setCheckThreadId(const bool check) {
+ check_thread_id_ = check;
+ }
+
/// @brief Allows or disallows the loopback interface
///
/// By default the loopback interface is not considered when opening
///
/// @param socketfd socket descriptor
/// @param callback callback function
+ ///
+ /// @note: all operations an external sockets should be performed
+ /// from the main thread as it does not make sense (and does not
+ /// work as expected) to use an external socket which is in fact
+ /// managed by an I/O service of a thread pool. For instance
+ /// a new external socket is scanned by select or poll only after
+ /// the next call to the receive method. Same argument applies
+ /// when an external socket is deleted and closed...
+ ///
+ /// @note: the callback is called when read available, hup and
+ /// error conditions: the callback is assumed to not block.
void addExternalSocket(int socketfd, SocketCallback callback);
/// @brief Checks if socket's file description is registered.
/// @brief Deletes all external sockets.
///
+ /// @note: to be used only in unit tests.
+ ///
/// External sockets should be removed from IfaceMgr before being closed
/// by the external API.
void deleteAllExternalSockets();
/// @brief Indicates if the IfaceMgr is in the test mode.
bool test_mode_;
+ /// Check thread ID when performing operations with external sockets.
+ std::atomic<bool> check_thread_id_;
+
/// @brief Detect callback used to perform actions before system dependent
/// function calls.
///