From 96eced777f6d8c34f5126d131d56ce1ad95896df Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Fri, 8 Dec 2017 23:07:31 +0100 Subject: [PATCH] FileDescriptorActivity: fix unit test failure related to almost concurrent removal of watched fd and write Signed-off-by: Johannes Meyer --- rtt/extras/FileDescriptorActivity.cpp | 30 +++++++++++++++++++++++---- tests/taskthread_fd_test.cpp | 3 +++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/rtt/extras/FileDescriptorActivity.cpp b/rtt/extras/FileDescriptorActivity.cpp index fe6bd77da..e6a35b7e7 100644 --- a/rtt/extras/FileDescriptorActivity.cpp +++ b/rtt/extras/FileDescriptorActivity.cpp @@ -389,14 +389,36 @@ void FileDescriptorActivity::loop() oro_atomic_set(&m_trigger, 0); do_trigger = true; } + if (oro_atomic_read(&m_update_sets) > 0) { + oro_atomic_set(&m_update_sets, 0); + + // Check if file descriptors that have work also have been removed in the current cycle and + // already ignore them. This is a corner case and still triggering an IOReady event would + // probably be fine in real-world applications, but it can break the task-test unit test + // depending on timing. + // + // The simple solution would be to continue without triggering the component, but we might miss + // triggers or activities on other file descriptors then. + // + // Disabled for now and patched in the unit test. + // +// { RTT::os::MutexLock lock(m_fd_lock); +// fd_set copy; +// FD_ZERO(©); +// m_has_ioready = false; +// for(int i = 0; i <= max_fd; ++i) { +// if (FD_ISSET(i, &m_fd_set) && FD_ISSET(i, &m_fd_work)) { +// FD_SET(i, ©); +// m_has_ioready = true; +// } +// } +// m_fd_work = copy; +// } + } if (oro_atomic_read(&m_break_loop) > 0) { oro_atomic_set(&m_break_loop, 0); break; } - if (oro_atomic_read(&m_update_sets) > 0) { - oro_atomic_set(&m_update_sets, 0); - continue; - } // Execute activity... if (m_has_timeout || m_has_ioready || do_trigger) diff --git a/tests/taskthread_fd_test.cpp b/tests/taskthread_fd_test.cpp index 73c414dec..79f91b5a8 100644 --- a/tests/taskthread_fd_test.cpp +++ b/tests/taskthread_fd_test.cpp @@ -218,6 +218,9 @@ BOOST_AUTO_TEST_CASE(testFileDescriptor_Write ) mtask->unwatch(mcomp.fd[0]); BOOST_CHECK( mtask->isWatched(mcomp.fd[0]) == false ); + // sleep to give the FileDescriptorActivity some time to update the internal file descriptor set + usleep(100000/10); + ++ch; rc = write(mcomp.fd[1], &ch, sizeof(ch)); if (1 != rc) std::cerr << "rc=" << rc << " errno=" << errno << ":" << strerror(errno) << std::endl;