From 911742f8b3798eaf03c56246539a402cc145eec8 Mon Sep 17 00:00:00 2001 From: Aleksandar Donchev Date: Wed, 27 Sep 2017 11:51:13 +0200 Subject: Runtime check for calls to the sockethandler from other threads Signed-off-by: Christian Linke Change-Id: I9d9d3c424ac9fad62c76a76545c731b518bdb1e2 --- AudioManagerUtilities/include/CAmSocketHandler.h | 6 ++ AudioManagerUtilities/src/CAmSocketHandler.cpp | 33 +++++- .../AmSocketHandlerTest/CAmSocketHandlerTest.cpp | 116 +++++++++++---------- 3 files changed, 99 insertions(+), 56 deletions(-) diff --git a/AudioManagerUtilities/include/CAmSocketHandler.h b/AudioManagerUtilities/include/CAmSocketHandler.h index d14c1a3..6163b3c 100644 --- a/AudioManagerUtilities/include/CAmSocketHandler.h +++ b/AudioManagerUtilities/include/CAmSocketHandler.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include "audiomanagertypes.h" @@ -309,6 +310,9 @@ class CAmSocketHandler #endif private: + + static void checkCallerThreadId(void); + bool fdIsValid(const int fd) const; timespec* insertTime(timespec& buffertime); @@ -496,6 +500,8 @@ public: void exit_mainloop(); bool fatalErrorOccurred(); + + static const std::thread::id SOCKETHANDLER_THREAD_ID; }; } /* namespace am */ diff --git a/AudioManagerUtilities/src/CAmSocketHandler.cpp b/AudioManagerUtilities/src/CAmSocketHandler.cpp index 54ba4ef..2a49770 100644 --- a/AudioManagerUtilities/src/CAmSocketHandler.cpp +++ b/AudioManagerUtilities/src/CAmSocketHandler.cpp @@ -32,6 +32,7 @@ #include #include + #include "CAmDltWrapper.h" #include "CAmSocketHandler.h" @@ -42,6 +43,9 @@ namespace am { +const std::thread::id CAmSocketHandler::SOCKETHANDLER_THREAD_ID = std::this_thread::get_id(); + + CAmSocketHandler::CAmSocketHandler() : mPipe(), // mDispatchDone(true), // @@ -102,6 +106,8 @@ void CAmSocketHandler::start_listenting() mDispatchDone = false; int16_t pollStatus; + checkCallerThreadId(); + #ifndef WITH_TIMERFD clock_gettime(CLOCK_MONOTONIC, &mStartTime); #endif @@ -253,6 +259,8 @@ am_Error_e CAmSocketHandler::getFDPollData(const sh_pollHandle_t handle, sh_poll */ am_Error_e CAmSocketHandler::listenToSignals(const std::vector & listSignals) { + checkCallerThreadId(); + int fdErr; uint8_t addedSignals = 0; sigset_t sigset; @@ -366,6 +374,8 @@ am_Error_e CAmSocketHandler::addFDPoll(const int fd, void* userData, sh_pollHandle_t& handle) { + checkCallerThreadId(); + if (!fdIsValid(fd)) return (E_NON_EXISTENT); @@ -435,6 +445,8 @@ am::am_Error_e CAmSocketHandler::addFDPoll(const int fd, const short event, IAmS */ am_Error_e CAmSocketHandler::removeFDPoll(const sh_pollHandle_t handle) { + checkCallerThreadId(); + VectorListPoll_t::iterator iterator = mListPoll.begin(); for (; iterator != mListPoll.end(); ++iterator) @@ -473,6 +485,8 @@ am_Error_e CAmSocketHandler::removeFDPoll(const sh_pollHandle_t handle) */ am_Error_e CAmSocketHandler::addSignalHandler(std::function callback, sh_pollHandle_t& handle, void * userData) { + checkCallerThreadId(); + if (!nextHandle(mSetSignalhandlerKeys)) { logError("Could not create new polls, too many open!"); @@ -495,6 +509,8 @@ am_Error_e CAmSocketHandler::addSignalHandler(std::function callback, sh_timerHandle_t& handle, void * userData, const bool repeats) { + checkCallerThreadId(); assert(!((timeouts.tv_sec == 0) && (timeouts.tv_nsec == 0))); mListTimer.emplace_back(); @@ -625,6 +642,7 @@ am_Error_e CAmSocketHandler::addTimer(const timespec & timeouts, std::function::iterator it = mListTimer.begin(); for (; it != mListTimer.end(); ++it) @@ -751,6 +771,7 @@ am_Error_e CAmSocketHandler::updateTimer(const sh_timerHandle_t handle, const ti */ am_Error_e CAmSocketHandler::restartTimer(const sh_timerHandle_t handle) { + checkCallerThreadId(); #ifdef WITH_TIMERFD std::list::iterator it = mListTimer.begin(); for (; it != mListTimer.end(); ++it) @@ -829,6 +850,7 @@ am_Error_e CAmSocketHandler::restartTimer(const sh_timerHandle_t handle) */ am_Error_e CAmSocketHandler::stopTimer(const sh_timerHandle_t handle) { + checkCallerThreadId(); #ifdef WITH_TIMERFD std::list::iterator it = mListTimer.begin(); for (; it != mListTimer.end(); ++it) @@ -875,6 +897,7 @@ am_Error_e CAmSocketHandler::stopTimer(const sh_timerHandle_t handle) */ am_Error_e CAmSocketHandler::updateEventFlags(const sh_pollHandle_t handle, const short events) { + checkCallerThreadId(); VectorListPoll_t::iterator iterator = mListPoll.begin(); for (; iterator != mListPoll.end(); ++iterator) @@ -889,6 +912,14 @@ am_Error_e CAmSocketHandler::updateEventFlags(const sh_pollHandle_t handle, cons return (E_UNKNOWN); } +void CAmSocketHandler::checkCallerThreadId(void) +{ + bool bSameThread = (std::this_thread::get_id() == CAmSocketHandler::SOCKETHANDLER_THREAD_ID); + if(!bSameThread) + logError("Sockethandler: Call from another thread detected!"); + assert(bSameThread); +} + /** * checks if a filedescriptor is validCAmShSubstractTime * @param fd the filedescriptor @@ -1064,7 +1095,7 @@ inline timespec* CAmSocketHandler::insertTime(timespec& buffertime) #ifdef WITH_TIMERFD am_Error_e CAmSocketHandler::createTimeFD(const itimerspec & timeouts, int & fd) -{ +{ fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); if (fd < 0) { diff --git a/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp b/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp index 07f6aaf..7e03f6e 100644 --- a/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp +++ b/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp @@ -252,16 +252,64 @@ void am::CAmTimerMeasurment::timerCallback(sh_timerHandle_t handle, void* userDa void* playWithSocketServer(void* data) { - CAmSocketHandler *pSockethandler = (CAmSocketHandler*) data; - pSockethandler->start_listenting(); + int socket_ = *((int*)data); + struct sockaddr_in servAddr; + unsigned short servPort = 6060; + struct hostent *host; + + if ((host = (struct hostent*) gethostbyname("localhost")) == 0) + { + std::cout << "ERROR: gethostbyname() failed\n" << std::endl; + exit(1); + } + + memset(&servAddr, 0, sizeof(servAddr)); + servAddr.sin_family = AF_INET; + servAddr.sin_addr.s_addr = inet_addr(inet_ntoa(*(struct in_addr*) (host->h_addr_list[0]))); + servAddr.sin_port = htons(servPort); + sleep(1); + + if (connect(socket_, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0) + { + std::cout << "ERROR: connect() failed\n" << std::endl; + } + + for (int i = 1; i <= SOCKET_TEST_LOOPS_COUNT; i++) + { + std::string string(TEST_SOCKET_DATA); + send(socket_, string.c_str(), string.size(), 0); + } + std::string string(TEST_SOCKET_DATA_FINAL); + send(socket_, string.c_str(), string.size(), 0); + return (NULL); } void* playWithUnixSocketServer(void* data) { - CAmSocketHandler *pSockethandler = (CAmSocketHandler*) data; - pSockethandler->start_listenting(); + int socket_ = *((int*)data); + struct sockaddr_un servAddr; + memset(&servAddr, 0, sizeof(servAddr)); + strcpy(servAddr.sun_path, SOCK_PATH); + servAddr.sun_family = AF_UNIX; + sleep(1); + + if (connect(socket_, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0) + { + std::cout << "ERROR: connect() failed\n" << std::endl; + } + + for (int i = 1; i <= SOCKET_TEST_LOOPS_COUNT; i++) + { + std::string stringToSend(TEST_SOCKET_DATA); + send(socket_, stringToSend.c_str(), stringToSend.size(), 0); + } + std::string stringToSend(TEST_SOCKET_DATA_FINAL); + send(socket_, stringToSend.c_str(), stringToSend.size(), 0); + return (NULL); + + } void* threadCallbackUnixSocketAndTimers(void* data) @@ -660,32 +708,16 @@ TEST(CAmSocketHandlerTest,playWithUNIXSockets) EXPECT_CALL(myplugin,dispatchData(_,_)).Times(SOCKET_TEST_LOOPS_COUNT + 1); EXPECT_CALL(myplugin,check(_,_)).Times(SOCKET_TEST_LOOPS_COUNT + 1); - //creates a thread that handles the serverpart - pthread_create(&serverThread, NULL, playWithUnixSocketServer, &myHandler); - - sleep(1); //we need that here because the port needs to be opened if ((socket_ = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { std::cout << "socket problem" << std::endl; - - } - - memset(&servAddr, 0, sizeof(servAddr)); - strcpy(servAddr.sun_path, SOCK_PATH); - servAddr.sun_family = AF_UNIX; - if (connect(socket_, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0) - { - std::cout << "ERROR: connect() failed\n" << std::endl; - } - - for (int i = 1; i <= SOCKET_TEST_LOOPS_COUNT; i++) - { - std::string stringToSend(TEST_SOCKET_DATA); - send(socket_, stringToSend.c_str(), stringToSend.size(), 0); } - std::string stringToSend(TEST_SOCKET_DATA_FINAL); - send(socket_, stringToSend.c_str(), stringToSend.size(), 0); + + //creates a thread that handles the serverpart + pthread_create(&serverThread, NULL, playWithUnixSocketServer, &socket_); + myHandler.start_listenting(); + pthread_join(serverThread, NULL); } @@ -693,9 +725,6 @@ TEST(CAmSocketHandlerTest,playWithUNIXSockets) TEST(CAmSocketHandlerTest,playWithSockets) { pthread_t serverThread; - struct sockaddr_in servAddr; - unsigned short servPort = 6060; - struct hostent *host; int socket_; CAmSocketHandler myHandler; @@ -707,39 +736,16 @@ TEST(CAmSocketHandlerTest,playWithSockets) EXPECT_CALL(myplugin,dispatchData(_,_)).Times(SOCKET_TEST_LOOPS_COUNT + 1); EXPECT_CALL(myplugin,check(_,_)).Times(SOCKET_TEST_LOOPS_COUNT + 1); - //creates a thread that handles the serverpart - pthread_create(&serverThread, NULL, playWithSocketServer, &myHandler); - - sleep(1); //we need that here because the port needs to be opened if ((socket_ = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { std::cout << "socket problem" << std::endl; } - if ((host = (struct hostent*) gethostbyname("localhost")) == 0) - { - std::cout << "ERROR: gethostbyname() failed\n" << std::endl; - exit(1); - } - - memset(&servAddr, 0, sizeof(servAddr)); - servAddr.sin_family = AF_INET; - servAddr.sin_addr.s_addr = inet_addr(inet_ntoa(*(struct in_addr*) (host->h_addr_list[0]))); - servAddr.sin_port = htons(servPort); - - if (connect(socket_, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0) - { - std::cout << "ERROR: connect() failed\n" << std::endl; - } - - for (int i = 1; i <= SOCKET_TEST_LOOPS_COUNT; i++) - { - std::string string(TEST_SOCKET_DATA); - send(socket_, string.c_str(), string.size(), 0); - } - std::string string(TEST_SOCKET_DATA_FINAL); - send(socket_, string.c_str(), string.size(), 0); + //creates a thread that handles the serverpart + pthread_create(&serverThread, NULL, playWithSocketServer, &socket_); + + myHandler.start_listenting(); pthread_join(serverThread, NULL); -- cgit v1.2.1