From be63615585049aa4045f13e91291d64b0a9ed5a3 Mon Sep 17 00:00:00 2001 From: Aleksandar Donchev Date: Fri, 19 May 2017 11:55:01 +0200 Subject: The primary signals SIGINT and SIGQUIT are handled on top level in contrast to secondary signals SIGHUP, SIGTERM, SIGCHLD, which are handled in the SocketHandler. Signed-off-by: Christian Linke Change-Id: I8c5d3c436ac9fcd61c76a26145c731b427cab1e6 --- AudioManagerCore/src/CAmCommandReceiver.cpp | 2 +- .../test/AmControlInterfaceTest/CMakeLists.txt | 1 + .../test/AmMapHandlerTest/CMakeLists.txt | 1 + .../test/AmRouterMapTest/CMakeLists.txt | 1 + AudioManagerCore/test/AmRouterTest/CMakeLists.txt | 1 + .../test/AmRoutingInterfaceTest/CMakeLists.txt | 1 + AudioManagerDaemon/src/main.cpp | 54 +- AudioManagerUtilities/include/CAmSocketHandler.h | 791 +++++----- AudioManagerUtilities/src/CAmSocketHandler.cpp | 1627 ++++++++++---------- .../test/AmSerializerTest/CMakeLists.txt | 1 + .../AmSocketHandlerTest/CAmSocketHandlerTest.cpp | 116 +- .../AmSocketHandlerTest/CAmSocketHandlerTest.h | 2 + .../test/AmSocketHandlerTest/CMakeLists.txt | 1 + CMakeLists.txt | 1 + docs/main_8cpp_source.html | 2 +- 15 files changed, 1344 insertions(+), 1258 deletions(-) diff --git a/AudioManagerCore/src/CAmCommandReceiver.cpp b/AudioManagerCore/src/CAmCommandReceiver.cpp index 0c6338a..ccf9612 100644 --- a/AudioManagerCore/src/CAmCommandReceiver.cpp +++ b/AudioManagerCore/src/CAmCommandReceiver.cpp @@ -120,7 +120,7 @@ am_Error_e CAmCommandReceiver::setMainSourceSoundProperty(const am_MainSoundProp am_Error_e CAmCommandReceiver::setSystemProperty(const am_SystemProperty_s & property) { - logInfo(__METHOD_NAME__,"type=", property.type, "soundPropertyValue=", property.value); + logInfo(__METHOD_NAME__,"type=", property.type, "systemPropertyValue=", property.value); return (mControlSender->hookUserSetSystemProperty(property)); } diff --git a/AudioManagerCore/test/AmControlInterfaceTest/CMakeLists.txt b/AudioManagerCore/test/AmControlInterfaceTest/CMakeLists.txt index f2636a8..b1a0dae 100644 --- a/AudioManagerCore/test/AmControlInterfaceTest/CMakeLists.txt +++ b/AudioManagerCore/test/AmControlInterfaceTest/CMakeLists.txt @@ -37,6 +37,7 @@ add_executable(AmControlInterfaceTest ${CONTROL_INTERFACE_SRCS_CXX}) TARGET_LINK_LIBRARIES(AmControlInterfaceTest ${GTEST_LIBRARIES} ${GMOCK_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} AudioManagerCore ) diff --git a/AudioManagerCore/test/AmMapHandlerTest/CMakeLists.txt b/AudioManagerCore/test/AmMapHandlerTest/CMakeLists.txt index 41c62c7..5a74cba 100644 --- a/AudioManagerCore/test/AmMapHandlerTest/CMakeLists.txt +++ b/AudioManagerCore/test/AmMapHandlerTest/CMakeLists.txt @@ -36,6 +36,7 @@ ADD_EXECUTABLE( AmMapHandlerTest ${DATABASE_SRCS_CXX}) TARGET_LINK_LIBRARIES( AmMapHandlerTest ${GTEST_LIBRARIES} ${GMOCK_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} AudioManagerCore ) diff --git a/AudioManagerCore/test/AmRouterMapTest/CMakeLists.txt b/AudioManagerCore/test/AmRouterMapTest/CMakeLists.txt index dc2732c..c4a5968 100644 --- a/AudioManagerCore/test/AmRouterMapTest/CMakeLists.txt +++ b/AudioManagerCore/test/AmRouterMapTest/CMakeLists.txt @@ -34,6 +34,7 @@ ADD_EXECUTABLE( AmRouterMapTest ${ROUTINGMAP_SRCS_CXX}) TARGET_LINK_LIBRARIES(AmRouterMapTest ${GTEST_LIBRARIES} ${GMOCK_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} AudioManagerCore ) diff --git a/AudioManagerCore/test/AmRouterTest/CMakeLists.txt b/AudioManagerCore/test/AmRouterTest/CMakeLists.txt index 89094c8..d866032 100644 --- a/AudioManagerCore/test/AmRouterTest/CMakeLists.txt +++ b/AudioManagerCore/test/AmRouterTest/CMakeLists.txt @@ -35,6 +35,7 @@ ADD_EXECUTABLE( AmRouterTest ${ROUTING_SRCS_CXX}) TARGET_LINK_LIBRARIES(AmRouterTest ${GTEST_LIBRARIES} ${GMOCK_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} AudioManagerCore ) diff --git a/AudioManagerCore/test/AmRoutingInterfaceTest/CMakeLists.txt b/AudioManagerCore/test/AmRoutingInterfaceTest/CMakeLists.txt index 6d47c15..369c536 100644 --- a/AudioManagerCore/test/AmRoutingInterfaceTest/CMakeLists.txt +++ b/AudioManagerCore/test/AmRoutingInterfaceTest/CMakeLists.txt @@ -38,6 +38,7 @@ ADD_TEST(AmRoutingInterfaceTest AmRoutingInterfaceTest) TARGET_LINK_LIBRARIES(AmRoutingInterfaceTest ${GTEST_LIBRARIES} ${GMOCK_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} AudioManagerCore ) diff --git a/AudioManagerDaemon/src/main.cpp b/AudioManagerDaemon/src/main.cpp index 4e8ca47..5c0582e 100755 --- a/AudioManagerDaemon/src/main.cpp +++ b/AudioManagerDaemon/src/main.cpp @@ -179,6 +179,36 @@ void printCmdInformation() exit(0); } +/** + * the signal handler + * @param sig + * @param siginfo + * @param context + */ +static void signalHandler(int sig, siginfo_t *siginfo, void *context) +{ + (void) sig; + (void) siginfo; + (void) context; + logInfo("signal handler was called, signal",sig); + + switch (sig) + { + /*ctl +c lets call direct controllerRundown, because we might be blocked at the moment. + But there is the risk of interrupting something important */ + case SIGINT: + CAmControlSender::CallsetControllerRundown(sig); + break; + + /* huch- we are getting killed. Better take the fast but risky way: */ + case SIGQUIT: + CAmControlSender::CallsetControllerRundown(sig); + break; + default: + break; + } +} + void mainProgram(int argc, char *argv[]) { @@ -220,6 +250,11 @@ void mainProgram(int argc, char *argv[]) { throw std::runtime_error(std::string("CAmSocketHandler: Could not create pipe or file descriptor is invalid.")); } + + if( E_OK!=iSocketHandler.listenToSignals({SIGHUP, SIGTERM, SIGCHLD}) ) + { + logWarning("CAmSocketHandler failed to register itself as signal handler."); + } //Register signal handler sh_pollHandle_t signalHandler; iSocketHandler.addSignalHandler([&](const sh_pollHandle_t handle, const signalfd_siginfo & info, void* userData){ @@ -231,17 +266,6 @@ void mainProgram(int argc, char *argv[]) switch (sig) { - /*ctl +c lets call direct controllerRundown, because we might be blocked at the moment. - But there is the risk of interrupting something important */ - case SIGINT: - CAmControlSender::CallsetControllerRundown(sig); - break; - - /* huch- we are getting killed. Better take the fast but risky way: */ - case SIGQUIT: - CAmControlSender::CallsetControllerRundown(sig); - break; - /* more friendly here assuming systemd wants to stop us, so we can use the mainloop */ case SIGTERM: CAmControlSender::CallsetControllerRundownSafe(sig); @@ -364,6 +388,14 @@ int main(int argc, char *argv[], char** envp) listCommandPluginDirs.push_back(std::string(DEFAULT_PLUGIN_COMMAND_DIR)); listRoutingPluginDirs.push_back(std::string(DEFAULT_PLUGIN_ROUTING_DIR)); + //critical signals are registered here: + struct sigaction signalAction; + memset(&signalAction, '\0', sizeof(signalAction)); + signalAction.sa_sigaction = &signalHandler; + signalAction.sa_flags = SA_SIGINFO; + sigaction(SIGINT, &signalAction, NULL); + sigaction(SIGQUIT, &signalAction, NULL); + //register new out of memory handler std::set_new_handler(&OutOfMemoryHandler); diff --git a/AudioManagerUtilities/include/CAmSocketHandler.h b/AudioManagerUtilities/include/CAmSocketHandler.h index 0f9b710..717f792 100644 --- a/AudioManagerUtilities/include/CAmSocketHandler.h +++ b/AudioManagerUtilities/include/CAmSocketHandler.h @@ -48,478 +48,447 @@ namespace am #define MAX_TIMERHANDLE UINT16_MAX #define MAX_POLLHANDLE UINT16_MAX - typedef uint16_t sh_pollHandle_t; //! class TAmShPollFired: public IAmShPollFired +{ +private: + TClass* mInstance; + void (TClass::*mFunction)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData); - /**make private, not public - * template for a callback - */ - template class TAmShPollFired: public IAmShPollFired +public: + TAmShPollFired(TClass* instance, void (TClass::*function)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)) : + mInstance(instance), // + mFunction(function) + {} + + virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData) { - private: - TClass* mInstance; - void (TClass::*mFunction)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData); - - public: - TAmShPollFired(TClass* instance, void (TClass::*function)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)) : - mInstance(instance), // - mFunction(function) - { - } - ; + (*mInstance.*mFunction)(pollfd, handle, userData); + } +}; - virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData) - { - (*mInstance.*mFunction)(pollfd, handle, userData); - } - ; - }; +/** + * template for a callback + */ +template class TAmShPollCheck: public IAmShPollCheck +{ +private: + TClass* mInstance; + bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData); - /** - * template for a callback - */ - template class TAmShPollCheck: public IAmShPollCheck +public: + TAmShPollCheck(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) : + mInstance(instance), // + mFunction(function) + {} + + virtual bool Call(const sh_pollHandle_t handle, void* userData) { - private: - TClass* mInstance; - bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData); - - public: - TAmShPollCheck(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) : - mInstance(instance), // - mFunction(function) - { - } - ; + return ((*mInstance.*mFunction)(handle, userData)); + } +}; - virtual bool Call(const sh_pollHandle_t handle, void* userData) - { - return ((*mInstance.*mFunction)(handle, userData)); - } - ; - }; +/** + * template for a callback + */ +template class TAmShPollDispatch: public IAmShPollDispatch +{ +private: + TClass* mInstance; + bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData); - /** - * template for a callback - */ - template class TAmShPollDispatch: public IAmShPollDispatch +public: + TAmShPollDispatch(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) : + mInstance(instance), // + mFunction(function) + {} + + virtual bool Call(const sh_pollHandle_t handle, void* userData) { - private: - TClass* mInstance; - bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData); - - public: - TAmShPollDispatch(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) : - mInstance(instance), // - mFunction(function) - { - } - ; + return ((*mInstance.*mFunction)(handle, userData)); + } +}; - virtual bool Call(const sh_pollHandle_t handle, void* userData) - { - return ((*mInstance.*mFunction)(handle, userData)); - } - ; - }; +/** + * template to create the functor for a class + */ +template class TAmShTimerCallBack: public IAmShTimerCallBack +{ +private: + TClass* mInstance; + void (TClass::*mFunction)(sh_timerHandle_t handle, void* userData); - /** - * template to create the functor for a class - */ - template class TAmShTimerCallBack: public IAmShTimerCallBack +public: + TAmShTimerCallBack(TClass* instance, void (TClass::*function)(sh_timerHandle_t handle, void* userData)) : + IAmShTimerCallBack(), mInstance(instance), // + mFunction(function) + {} + + virtual void Call(sh_timerHandle_t handle, void* userData) { - private: - TClass* mInstance; - void (TClass::*mFunction)(sh_timerHandle_t handle, void* userData); - - public: - TAmShTimerCallBack(TClass* instance, void (TClass::*function)(sh_timerHandle_t handle, void* userData)) : - IAmShTimerCallBack(), mInstance(instance), // - mFunction(function) - { - } - ; + (*mInstance.*mFunction)(handle, userData); + } +}; - virtual void Call(sh_timerHandle_t handle, void* userData) - { - (*mInstance.*mFunction)(handle, userData); - } - }; +/** + * template for a callback + */ - /** - * template for a callback - */ +template class TAmShPollPrepare: public IAmShPollPrepare +{ +private: + TClass* mInstance; + void (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData); - template class TAmShPollPrepare: public IAmShPollPrepare +public: + TAmShPollPrepare(TClass* instance, void (TClass::*function)(const sh_pollHandle_t handle, void* userData)) : + mInstance(instance), // + mFunction(function) + {} + + virtual void Call(const sh_pollHandle_t handle, void* userData) { - private: - TClass* mInstance; - void (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData); - - public: - TAmShPollPrepare(TClass* instance, void (TClass::*function)(const sh_pollHandle_t handle, void* userData)) : - mInstance(instance), // - mFunction(function) - { - } - ; + (*mInstance.*mFunction)(handle, userData); + } +}; - virtual void Call(const sh_pollHandle_t handle, void* userData) - { - (*mInstance.*mFunction)(handle, userData); - } - ; +/** + * The am::CAmSocketHandler implements a mainloop for the AudioManager. Plugins and different parts of the AudioManager add their filedescriptors to the handler + * to get called on communication of the filedescriptors.\n + * More information can be found here : \ref mainl + */ +class CAmSocketHandler +{ + struct sh_poll_s //! prepareCB; //preperation callback + std::function firedCB; //fired callback + std::function checkCB; //check callback + std::function dispatchCB; //dispatch callback + void* userData; + + sh_poll_s() : + handle(0), pollfdValue(), prepareCB(), firedCB(), checkCB(), dispatchCB(), userData(0) + {} }; - /** - * The am::CAmSocketHandler implements a mainloop for the AudioManager. Plugins and different parts of the AudioManager add their filedescriptors to the handler - * to get called on communication of the filedescriptors.\n - * More information can be found here : \ref mainl - */ - class CAmSocketHandler + struct sh_timer_s //! prepareCB; //preperation callback - std::function firedCB; //fired callback - std::function checkCB; //check callback - std::function dispatchCB; //dispatch callback - void* userData; - - sh_poll_s() : - handle(0), pollfdValue(), prepareCB(), firedCB(), checkCB(), dispatchCB(), userData(0) - { - } - }; - - struct sh_timer_s //! callback; //timer callback - void* userData; - sh_timer_s() : - handle(0) + std::function callback; //timer callback + void* userData; + sh_timer_s() : + handle(0) #ifdef WITH_TIMERFD - , fd(0) + , fd(0) #endif - , countdown(), callback(), userData(0) - { - } - }; + , countdown(), callback(), userData(0) + {} + }; - struct sh_signal_s - { - sh_pollHandle_t handle; //! callback; - void* userData; - sh_signal_s() : - handle(0), callback(), userData(0) - { - } - }; + struct sh_signal_s + { + sh_pollHandle_t handle; //! callback; + void* userData; + sh_signal_s() : + handle(0), callback(), userData(0) + {} + }; - struct sh_identifier_s - { - std::set pollHandles; - uint16_t limit; - uint16_t lastUsedID; - sh_identifier_s(const uint16_t pollLimit = UINT16_MAX) : - pollHandles(), limit(pollLimit), lastUsedID(0) - { - } - }; + struct sh_identifier_s + { + std::set pollHandles; + uint16_t limit; + uint16_t lastUsedID; + sh_identifier_s(const uint16_t pollLimit = UINT16_MAX) : + pollHandles(), limit(pollLimit), lastUsedID(0) + {} + }; - typedef std::reverse_iterator rListTimerIter; //! VectorListPollfd_t; //! VectorListPoll_t; //! VectorSignalHandlers_t; //! rListTimerIter; //! VectorListPollfd_t; //! VectorListPoll_t; //! VectorSignalHandlers_t; //! mListTimer; //! mListActiveTimer; //! mListTimer; //! mListActiveTimer; //!= MAX_NS) { - timespec result; - result.tv_sec = a.tv_sec + b.tv_sec; - result.tv_nsec = a.tv_nsec + b.tv_nsec; - if (result.tv_nsec >= MAX_NS) - { - result.tv_sec++; - result.tv_nsec = result.tv_nsec - MAX_NS; - } - return (result); + result.tv_sec++; + result.tv_nsec = result.tv_nsec - MAX_NS; } + return (result); + } - /** - * comapares timespec values - * @param a - * @param b - * @return - */ - inline int timespecCompare(const timespec& a, const timespec& b) - { - //less - if (a.tv_sec < b.tv_sec) - return (-1); - //greater - else if (a.tv_sec > b.tv_sec) - return (1); - //less - else if (a.tv_nsec < b.tv_nsec) - return (-1); - //greater - else if (a.tv_nsec > b.tv_nsec) - return (1); - //equal - return (0); - } + /** + * comapares timespec values + * @param a + * @param b + * @return + */ + inline int timespecCompare(const timespec& a, const timespec& b) + { + //less + if (a.tv_sec < b.tv_sec) + return (-1); + //greater + else if (a.tv_sec > b.tv_sec) + return (1); + //less + else if (a.tv_nsec < b.tv_nsec) + return (-1); + //greater + else if (a.tv_nsec > b.tv_nsec) + return (1); + //equal + return (0); + } #endif - /** - * functor to prepare all fire events - * @param a - * @return - */ - inline static void prepare(sh_poll_s& row); + /** + * functor to prepare all fire events + * @param a + * @return + */ + inline static void prepare(sh_poll_s& row); + + /** + * functor to return all fired events + * @param a + * @return + */ + inline static void fire(sh_poll_s& a); + + /** + * functor to return all fired events + * @param a + * @return + */ + inline static bool eventFired(const pollfd& a); + + /** + * functor to help find the items that do not need dispatching + * @param a + * @return + */ + inline static bool noDispatching(const sh_poll_s& a); + + /** + * checks if dispatching is already finished + * @param a + * @return + */ + inline static bool dispatchingFinished(const sh_poll_s& a); + + /** + * timer fire callback + * @param a + * @return + */ + inline static void callTimer(sh_timer_s& a); + + /** + * next handle id + * @param std::set handles + * @return handle + */ + bool nextHandle(sh_identifier_s & handle); + + am_Error_e getFDPollData(const sh_pollHandle_t handle, sh_poll_s & outPollData); + +public: + + CAmSocketHandler(); + ~CAmSocketHandler(); - /** - * functor to return all fired events - * @param a - * @return - */ - inline static void fire(sh_poll_s& a); - - /** - * functor to return all fired events - * @param a - * @return - */ - inline static bool eventFired(const pollfd& a); - - /** - * functor to help find the items that do not need dispatching - * @param a - * @return - */ - inline static bool noDispatching(const sh_poll_s& a); - - /** - * checks if dispatching is already finished - * @param a - * @return - */ - inline static bool dispatchingFinished(const sh_poll_s& a); - - /** - * timer fire callback - * @param a - * @return - */ - inline static void callTimer(sh_timer_s& a); - - /** - * install the signal fd - */ - - am_Error_e addSignalFd(); - /** - * next handle id - * @param std::set handles - * @return handle - */ - bool nextHandle(sh_identifier_s & handle); - - public: - - CAmSocketHandler(); - ~CAmSocketHandler(); - - am_Error_e addFDPoll(const int fd, const short event, std::function prepare, std::function fired, - std::function check, std::function dispatch, void* userData, sh_pollHandle_t& handle); - - am_Error_e addFDPoll(const int fd, const short event, IAmShPollPrepare *prepare, IAmShPollFired *fired, IAmShPollCheck *check, IAmShPollDispatch *dispatch, void* userData, sh_pollHandle_t& handle); - am_Error_e removeFDPoll(const sh_pollHandle_t handle); - am_Error_e updateEventFlags(const sh_pollHandle_t handle, const short events); - am_Error_e addSignalHandler(std::function callback, sh_pollHandle_t& handle, void * userData); - am_Error_e removeSignalHandler(const sh_pollHandle_t handle); - am_Error_e addTimer(const timespec & timeouts, IAmShTimerCallBack* callback, sh_timerHandle_t& handle, void * userData, + /** + * install the signal fd + */ + am_Error_e listenToSignals(const std::vector & listSignals); + + am_Error_e addFDPoll(const int fd, const short event, std::function prepare, std::function fired, + std::function check, std::function dispatch, void* userData, sh_pollHandle_t& handle); + + am_Error_e addFDPoll(const int fd, const short event, IAmShPollPrepare *prepare, IAmShPollFired *fired, IAmShPollCheck *check, IAmShPollDispatch *dispatch, void* userData, sh_pollHandle_t& handle); + am_Error_e removeFDPoll(const sh_pollHandle_t handle); + am_Error_e updateEventFlags(const sh_pollHandle_t handle, const short events); + am_Error_e addSignalHandler(std::function callback, sh_pollHandle_t& handle, void * userData); + am_Error_e removeSignalHandler(const sh_pollHandle_t handle); + am_Error_e addTimer(const timespec & timeouts, IAmShTimerCallBack* callback, sh_timerHandle_t& handle, void * userData, #ifndef WITH_TIMERFD - const bool __attribute__((__unused__)) repeats = false + const bool __attribute__((__unused__)) repeats = false #else - const bool repeats = false + const bool repeats = false #endif - ); - am_Error_e addTimer(const timespec & timeouts, std::function callback, sh_timerHandle_t& handle, void* userData, + ); + am_Error_e addTimer(const timespec & timeouts, std::function callback, sh_timerHandle_t& handle, void* userData, #ifndef WITH_TIMERFD - const bool __attribute__((__unused__)) repeats = false + const bool __attribute__((__unused__)) repeats = false #else - const bool repeats = false + const bool repeats = false #endif - ); - am_Error_e removeTimer(const sh_timerHandle_t handle); - am_Error_e restartTimer(const sh_timerHandle_t handle); - am_Error_e updateTimer(const sh_timerHandle_t handle, const timespec & timeouts); - am_Error_e stopTimer(const sh_timerHandle_t handle); - void start_listenting(); - void stop_listening(); - void exit_mainloop(); - - bool fatalErrorOccurred() { return ((mError&internal_error_codes_e::PIPE_ERROR)>0)||((mError&internal_error_codes_e::FD_ERROR)>0); } - }; + ); + am_Error_e removeTimer(const sh_timerHandle_t handle); + am_Error_e restartTimer(const sh_timerHandle_t handle); + am_Error_e updateTimer(const sh_timerHandle_t handle, const timespec & timeouts); + am_Error_e stopTimer(const sh_timerHandle_t handle); + void start_listenting(); + void stop_listening(); + void exit_mainloop(); + + bool fatalErrorOccurred(); +}; } /* namespace am */ #endif /* SOCKETHANDLER_H_ */ diff --git a/AudioManagerUtilities/src/CAmSocketHandler.cpp b/AudioManagerUtilities/src/CAmSocketHandler.cpp index fe7cf58..7b0fc5d 100644 --- a/AudioManagerUtilities/src/CAmSocketHandler.cpp +++ b/AudioManagerUtilities/src/CAmSocketHandler.cpp @@ -42,998 +42,1039 @@ namespace am { - CAmSocketHandler::CAmSocketHandler() : - mPipe(), // - mDispatchDone(1), // - mSetPollKeys(MAX_POLLHANDLE), // - mListPoll(), // - mSetTimerKeys(MAX_TIMERHANDLE), - mListTimer(), // - mListActiveTimer(), // - mSetSignalhandlerKeys(MAX_POLLHANDLE), // - mSignalHandlers(), // - mRecreatePollfds(true), - mError(internal_error_codes_e::NO_ERROR) +CAmSocketHandler::CAmSocketHandler() : + mPipe(), // + mDispatchDone(true), // + mSetPollKeys(MAX_POLLHANDLE), // + mListPoll(), // + mSetTimerKeys(MAX_TIMERHANDLE), + mListTimer(), // + mListActiveTimer(), // + mSetSignalhandlerKeys(MAX_POLLHANDLE), // + mSignalHandlers(), // + mRecreatePollfds(true), + mInternalCodes(internal_codes_e::NO_ERROR), + mSignalFdHandle(0) #ifndef WITH_TIMERFD - ,mStartTime() // +,mStartTime() // #endif +{ + if (pipe(mPipe) == -1) { - if (pipe(mPipe) == -1) - { - mError = internal_error_codes_e::PIPE_ERROR; - logError("Sockethandler could not create pipe!"); - } - - //add the pipe to the poll - nothing needs to be processed here we just need the pipe to trigger the ppoll - short event = 0; - sh_pollHandle_t handle; - event |= POLLIN; - if (addFDPoll(mPipe[0], event, NULL, [](const pollfd pollfd, const sh_pollHandle_t, void*) - {}, [](const sh_pollHandle_t, void*) - { return (false);}, NULL, NULL, handle) != E_OK) - mError |= internal_error_codes_e::FD_ERROR; - if (addSignalFd() != E_OK) - mError |= internal_error_codes_e::SFD_ERROR; + mInternalCodes = internal_codes_e::PIPE_ERROR; + logError("Sockethandler could not create pipe!"); } - CAmSocketHandler::~CAmSocketHandler() + //add the pipe to the poll - nothing needs to be processed here we just need the pipe to trigger the ppoll + short event = 0; + sh_pollHandle_t handle; + event |= POLLIN; + if (addFDPoll(mPipe[0], event, NULL, [](const pollfd pollfd, const sh_pollHandle_t, void*) + {}, [](const sh_pollHandle_t, void*) + { return (false);}, NULL, NULL, handle) != E_OK) + mInternalCodes |= internal_codes_e::FD_ERROR; +} + +CAmSocketHandler::~CAmSocketHandler() +{ + for (auto it : mListPoll) { - for (auto it : mListPoll) - { - close(it.pollfdValue.fd); - } - close(mPipe[0]); - close(mPipe[1]); + close(it.pollfdValue.fd); } + close(mPipe[0]); + close(mPipe[1]); +} //todo: maybe have some: give me more time returned? - /** - * start the block listening for filedescriptors. This is the mainloop. - */ - void CAmSocketHandler::start_listenting() - { - mDispatchDone = 0; - int16_t pollStatus; - - //prepare the signalmask - sigset_t sigmask; - sigemptyset(&sigmask); - sigaddset(&sigmask, SIGINT); - sigaddset(&sigmask, SIGQUIT); - sigaddset(&sigmask, SIGTERM); - sigaddset(&sigmask, SIGHUP); - sigaddset(&sigmask, SIGQUIT); +/** + * start the block listening for filedescriptors. This is the mainloop. + */ +void CAmSocketHandler::start_listenting() +{ + mDispatchDone = false; + int16_t pollStatus; + #ifndef WITH_TIMERFD - clock_gettime(CLOCK_MONOTONIC, &mStartTime); + clock_gettime(CLOCK_MONOTONIC, &mStartTime); #endif - timespec buffertime; - - std::list listPoll; - VectorListPoll_t cloneListPoll; - VectorListPoll_t::iterator listmPollIt; - VectorListPollfd_t::iterator itMfdPollingArray; - VectorListPollfd_t fdPollingArray; //! listPoll; + VectorListPoll_t cloneListPoll; + VectorListPoll_t::iterator listmPollIt; + VectorListPollfd_t::iterator itMfdPollingArray; + VectorListPollfd_t fdPollingArray; //!0)||((mInternalCodes&internal_codes_e::FD_ERROR)>0); +} + +am_Error_e CAmSocketHandler::getFDPollData(const sh_pollHandle_t handle, sh_poll_s & outPollData) +{ + VectorListPoll_t::iterator iterator = mListPoll.begin(); + for (; iterator != mListPoll.end(); ++iterator) + { + if (iterator->handle == handle) { - logError("Could not create sigset!"); - return (E_NOT_POSSIBLE); + outPollData = *iterator; + return (E_OK); } - fdErr = sigaddset(&sigset, SIGINT); - if (fdErr != 0) - logWarning("Could not add SIGINT"); - fdErr = sigaddset(&sigset, SIGHUP); - if (fdErr != 0) - logWarning("Could not add SIGHUP"); - fdErr = sigaddset(&sigset, SIGQUIT); - if (fdErr != 0) - logWarning("Could not add SIGQUIT"); - fdErr = sigaddset(&sigset, SIGTERM); - if (fdErr != 0) - logWarning("Could not add SIGTERM"); - fdErr = sigaddset(&sigset, SIGCHLD); - if (fdErr != 0) - logWarning("Could not add SIGCHLD"); + } + return (E_UNKNOWN); +} - /* We must block the signals in order for signalfd to receive them */ - fdErr = sigprocmask(SIG_BLOCK, &sigset, NULL); +/** + * Adds a signal handler filedescriptor to the polling loop + * + */ +am_Error_e CAmSocketHandler::listenToSignals(const std::vector & listSignals) +{ + int fdErr; + uint8_t addedSignals = 0; + sigset_t sigset; + + if(0==listSignals.size()) + { + logWarning("Empty signal list!"); + return (E_NOT_POSSIBLE); + } + + /* Create a sigset of all the signals that we're interested in */ + fdErr = sigemptyset(&sigset); + if (fdErr != 0) + { + logError("Could not create sigset!"); + return (E_NOT_POSSIBLE); + } + + for(uint8_t itSignal : listSignals) + { + fdErr = sigaddset(&sigset, itSignal); if (fdErr != 0) - { - logError("Could not block signals! They must be blocked in order to receive them!"); - return (E_NOT_POSSIBLE); - } + logWarning("Could not add", itSignal); + else + addedSignals++; + } + + if(0==addedSignals) + { + logWarning("None of the signals were added!"); + return (E_NOT_POSSIBLE); + } - /* Create the signalfd */ - int signalHandlerFd = signalfd(-1, &sigset, 0); + /* We must block the signals in order for signalfd to receive them */ + fdErr = sigprocmask(SIG_BLOCK, &sigset, NULL); + if (fdErr != 0) + { + logError("Could not block signals! They must be blocked in order to receive them!"); + return (E_NOT_POSSIBLE); + } + + int signalHandlerFd; + if(mSignalFdHandle) + { + sh_poll_s sgPollData; + if(E_OK!=getFDPollData(mSignalFdHandle, sgPollData)) + { + removeFDPoll(mSignalFdHandle); + mSignalFdHandle = 0; + } + else + { + int signalHandlerFd = signalfd(sgPollData.pollfdValue.fd, &sigset, 0); if (signalHandlerFd == -1) { - logError("Could not open signal fd!"); + logError("Could not update signal fd!"); return (E_NOT_POSSIBLE); } - - auto actionPoll = [this](const pollfd pollfd, const sh_pollHandle_t, void*) - { - const VectorSignalHandlers_t & signalHandlers = mSignalHandlers; - /* We have a valid signal, read the info from the fd */ - struct signalfd_siginfo info; - ssize_t bytes = read(pollfd.fd, &info, sizeof(info)); - assert(bytes == sizeof(info)); - - /* We have a valid signal, read the info from the fd */ - for(auto it: signalHandlers) - it.callback(it.handle, info, it.userData); - }; - /* We're going to add the signal fd through addFDPoll. At this point we don't have any signal listeners. */ - return addFDPoll(signalHandlerFd, POLLIN | POLLERR | POLLHUP, NULL, actionPoll, [](const sh_pollHandle_t, void*) - { return (false);}, NULL, NULL, handle); + return E_OK; + } } + + if(0==mSignalFdHandle) + { + /* Create the signalfd */ + signalHandlerFd = signalfd(-1, &sigset, 0); + if (signalHandlerFd == -1) + { + logError("Could not open signal fd!"); + return (E_NOT_POSSIBLE); + } + + auto actionPoll = [this](const pollfd pollfd, const sh_pollHandle_t, void*) + { + const VectorSignalHandlers_t & signalHandlers = mSignalHandlers; + /* We have a valid signal, read the info from the fd */ + struct signalfd_siginfo info; + ssize_t bytes = read(pollfd.fd, &info, sizeof(info)); + assert(bytes == sizeof(info)); + + /* Notify all listeners */ + for(auto it: signalHandlers) + it.callback(it.handle, info, it.userData); + }; + /* We're going to add the signal fd through addFDPoll. At this point we don't have any signal listeners. */ + am_Error_e shFdError = addFDPoll(signalHandlerFd, POLLIN | POLLERR | POLLHUP, NULL, actionPoll, [](const sh_pollHandle_t, void*) + { return (false);}, NULL, NULL, mSignalFdHandle); + return shFdError; + } +} + +/** + * Adds a filedescriptor to the polling loop + * @param fd the filedescriptor + * @param event the event flags + * @param prepare a std::function that is called before the loop is entered + * @param fired a std::function that is called when the filedescriptor needs to be read + * @param check a std::function that is called to check if further actions are neccessary + * @param dispatch a std::function that is called to dispatch the received data + * @param userData a pointer to userdata that is always passed around + * @param handle the handle of this poll + * @return E_OK if the descriptor was added, E_NON_EXISTENT if the fd is not valid + */ + +am_Error_e CAmSocketHandler::addFDPoll(const int fd, const short event, std::function prepare, + std::function fired, std::function check, + std::function dispatch, void* userData, sh_pollHandle_t& handle) +{ + if (!fdIsValid(fd)) + return (E_NON_EXISTENT); - /** - * Adds a filedescriptor to the polling loop - * @param fd the filedescriptor - * @param event the event flags - * @param prepare a std::function that is called before the loop is entered - * @param fired a std::function that is called when the filedescriptor needs to be read - * @param check a std::function that is called to check if further actions are neccessary - * @param dispatch a std::function that is called to dispatch the received data - * @param userData a pointer to userdata that is always passed around - * @param handle the handle of this poll - * @return E_OK if the descriptor was added, E_NON_EXISTENT if the fd is not valid - */ - - am_Error_e CAmSocketHandler::addFDPoll(const int fd, const short event, std::function prepare, - std::function fired, std::function check, - std::function dispatch, void* userData, sh_pollHandle_t& handle) + //create a new handle for the poll + if (!nextHandle(mSetPollKeys)) { - if (!fdIsValid(fd)) - return (E_NON_EXISTENT); + logError("Could not create new polls, too many open!"); + return (E_NOT_POSSIBLE); + } - //create a new handle for the poll - if (!nextHandle(mSetPollKeys)) - { - logError("Could not create new polls, too many open!"); - return (E_NOT_POSSIBLE); - } + sh_poll_s pollData; + pollData.pollfdValue.fd = fd; + pollData.handle = mSetPollKeys.lastUsedID; + pollData.pollfdValue.events = event; + pollData.pollfdValue.revents = 0; + pollData.prepareCB = prepare; + pollData.firedCB = fired; + pollData.checkCB = check; + pollData.dispatchCB = dispatch; + pollData.userData = userData; + //add new data to the list + mListPoll.push_back(pollData); - sh_poll_s pollData; - pollData.pollfdValue.fd = fd; - pollData.handle = mSetPollKeys.lastUsedID; - pollData.pollfdValue.events = event; - pollData.pollfdValue.revents = 0; - pollData.prepareCB = prepare; - pollData.firedCB = fired; - pollData.checkCB = check; - pollData.dispatchCB = dispatch; - pollData.userData = userData; - //add new data to the list - mListPoll.push_back(pollData); + mRecreatePollfds = true; - mRecreatePollfds = true; + handle = pollData.handle; + return (E_OK); - handle = pollData.handle; - return (E_OK); +} - } +/** + * Adds a filedescriptor to the polling loop + * @param fd the filedescriptor + * @param event the event flags + * @param prepare a callback that is called before the loop is entered + * @param fired a callback that is called when the filedescriptor needs to be read + * @param check a callback that is called to check if further actions are neccessary + * @param dispatch a callback that is called to dispatch the received data + * @param userData a pointer to userdata that is always passed around + * @param handle the handle of this poll + * @return E_OK if the descriptor was added, E_NON_EXISTENT if the fd is not valid + */ +am::am_Error_e CAmSocketHandler::addFDPoll(const int fd, const short event, IAmShPollPrepare *prepare, IAmShPollFired *fired, IAmShPollCheck *check, IAmShPollDispatch *dispatch, void *userData, sh_pollHandle_t & handle) +{ - /** - * Adds a filedescriptor to the polling loop - * @param fd the filedescriptor - * @param event the event flags - * @param prepare a callback that is called before the loop is entered - * @param fired a callback that is called when the filedescriptor needs to be read - * @param check a callback that is called to check if further actions are neccessary - * @param dispatch a callback that is called to dispatch the received data - * @param userData a pointer to userdata that is always passed around - * @param handle the handle of this poll - * @return E_OK if the descriptor was added, E_NON_EXISTENT if the fd is not valid - */ - am::am_Error_e CAmSocketHandler::addFDPoll(const int fd, const short event, IAmShPollPrepare *prepare, IAmShPollFired *fired, IAmShPollCheck *check, IAmShPollDispatch *dispatch, void *userData, sh_pollHandle_t & handle) - { + std::function prepareCB; //preperation callback + std::function firedCB; //fired callback + std::function checkCB; //check callback + std::function dispatchCB; //check callback + + if (prepare) + prepareCB = std::bind(&IAmShPollPrepare::Call, prepare, std::placeholders::_1, std::placeholders::_2); + if (fired) + firedCB = std::bind(&IAmShPollFired::Call, fired, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); + if (check) + checkCB = std::bind(&IAmShPollCheck::Call, check, std::placeholders::_1, std::placeholders::_2); + if (dispatch) + dispatchCB = std::bind(&IAmShPollDispatch::Call, dispatch, std::placeholders::_1, std::placeholders::_2); + + return addFDPoll(fd, event, prepareCB, firedCB, checkCB, dispatchCB, userData, handle); +} - std::function prepareCB; //preperation callback - std::function firedCB; //fired callback - std::function checkCB; //check callback - std::function dispatchCB; //check callback - - if (prepare) - prepareCB = std::bind(&IAmShPollPrepare::Call, prepare, std::placeholders::_1, std::placeholders::_2); - if (fired) - firedCB = std::bind(&IAmShPollFired::Call, fired, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); - if (check) - checkCB = std::bind(&IAmShPollCheck::Call, check, std::placeholders::_1, std::placeholders::_2); - if (dispatch) - dispatchCB = std::bind(&IAmShPollDispatch::Call, dispatch, std::placeholders::_1, std::placeholders::_2); - - return addFDPoll(fd, event, prepareCB, firedCB, checkCB, dispatchCB, userData, handle); - } +/** + * removes a filedescriptor from the poll loop + * @param handle + * @return + */ +am_Error_e CAmSocketHandler::removeFDPoll(const sh_pollHandle_t handle) +{ + VectorListPoll_t::iterator iterator = mListPoll.begin(); - /** - * removes a filedescriptor from the poll loop - * @param handle - * @return - */ - am_Error_e CAmSocketHandler::removeFDPoll(const sh_pollHandle_t handle) + for (; iterator != mListPoll.end(); ++iterator) { - VectorListPoll_t::iterator iterator = mListPoll.begin(); - - for (; iterator != mListPoll.end(); ++iterator) + if (iterator->handle == handle) { - if (iterator->handle == handle) - { - iterator = mListPoll.erase(iterator); - mSetPollKeys.pollHandles.erase(handle); - mRecreatePollfds = true; - return (E_OK); - } + iterator = mListPoll.erase(iterator); + mSetPollKeys.pollHandles.erase(handle); + mRecreatePollfds = true; + return (E_OK); } - return (E_UNKNOWN); } + return (E_UNKNOWN); +} - /** - * Adds a callback for any signals - * @param callback - * @param handle the handle of this poll - * @param userData a pointer to userdata that is always passed around - * @return E_OK if the descriptor was added, E_NON_EXISTENT if the fd is not valid - */ - am_Error_e CAmSocketHandler::addSignalHandler(std::function callback, sh_pollHandle_t& handle, void * userData) +/** + * Adds a callback for any signals + * @param callback + * @param handle the handle of this poll + * @param userData a pointer to userdata that is always passed around + * @return E_OK if the descriptor was added, E_NON_EXISTENT if the fd is not valid + */ +am_Error_e CAmSocketHandler::addSignalHandler(std::function callback, sh_pollHandle_t& handle, void * userData) +{ + if (!nextHandle(mSetSignalhandlerKeys)) { - if (!nextHandle(mSetSignalhandlerKeys)) - { - logError("Could not create new polls, too many open!"); - return (E_NOT_POSSIBLE); - } + logError("Could not create new polls, too many open!"); + return (E_NOT_POSSIBLE); + } - mSignalHandlers.emplace_back(); - mSignalHandlers.back().callback = callback; - mSignalHandlers.back().handle = mSetSignalhandlerKeys.lastUsedID; - mSignalHandlers.back().userData = userData; - handle = mSetSignalhandlerKeys.lastUsedID; + mSignalHandlers.emplace_back(); + mSignalHandlers.back().callback = callback; + mSignalHandlers.back().handle = mSetSignalhandlerKeys.lastUsedID; + mSignalHandlers.back().userData = userData; + handle = mSetSignalhandlerKeys.lastUsedID; - return E_OK; - } + return E_OK; +} - /** - * removes a signal handler from the list - * @param handle is signal handler id - * @return E_OK in case of success, E_UNKNOWN if the handler was not found. - */ - am_Error_e CAmSocketHandler::removeSignalHandler(const sh_pollHandle_t handle) +/** + * removes a signal handler from the list + * @param handle is signal handler id + * @return E_OK in case of success, E_UNKNOWN if the handler was not found. + */ +am_Error_e CAmSocketHandler::removeSignalHandler(const sh_pollHandle_t handle) +{ + VectorSignalHandlers_t::iterator it(mSignalHandlers.begin()); + for (; it != mSignalHandlers.end(); ++it) { - VectorSignalHandlers_t::iterator it(mSignalHandlers.begin()); - for (; it != mSignalHandlers.end(); ++it) + if (it->handle == handle) { - if (it->handle == handle) - { - it = mSignalHandlers.erase(it); - mSetSignalhandlerKeys.pollHandles.erase(handle); - return (E_OK); - } + it = mSignalHandlers.erase(it); + mSetSignalhandlerKeys.pollHandles.erase(handle); + return (E_OK); } - return (E_UNKNOWN); } + return (E_UNKNOWN); +} - /** - * adds a timer to the list of timers. The callback will be fired when the timer is up. - * This is not a high precise timer, it is very coarse. It is meant to be used for timeouts when waiting - * for an answer via a filedescriptor. - * One time timer. If you need again a timer, you need to add a new timer in the callback of the old one. - * @param timeouts timeouts time until the callback is fired - * @param callback callback the callback - * @param handle handle the handle that is created for the timer is returned. Can be used to remove the timer - * @param userData pointer always passed with the call - * @return E_OK in case of success - */ - - am_Error_e CAmSocketHandler::addTimer(const timespec & timeouts, IAmShTimerCallBack* callback, sh_timerHandle_t& handle, void * userData, const bool repeats) - { - assert(callback!=NULL); +/** + * adds a timer to the list of timers. The callback will be fired when the timer is up. + * This is not a high precise timer, it is very coarse. It is meant to be used for timeouts when waiting + * for an answer via a filedescriptor. + * One time timer. If you need again a timer, you need to add a new timer in the callback of the old one. + * @param timeouts timeouts time until the callback is fired + * @param callback callback the callback + * @param handle handle the handle that is created for the timer is returned. Can be used to remove the timer + * @param userData pointer always passed with the call + * @return E_OK in case of success + */ + +am_Error_e CAmSocketHandler::addTimer(const timespec & timeouts, IAmShTimerCallBack* callback, sh_timerHandle_t& handle, void * userData, const bool repeats) +{ + assert(callback!=NULL); - std::function callbackFunc; - callbackFunc = std::bind(&IAmShTimerCallBack::Call, callback, std::placeholders::_1, std::placeholders::_2); + std::function callbackFunc; + callbackFunc = std::bind(&IAmShTimerCallBack::Call, callback, std::placeholders::_1, std::placeholders::_2); - return addTimer(timeouts, callbackFunc, handle, userData, repeats); - } + return addTimer(timeouts, callbackFunc, handle, userData, repeats); +} - am_Error_e CAmSocketHandler::addTimer(const timespec & timeouts, std::function callback, sh_timerHandle_t& handle, void * userData, const bool repeats) - { - assert(!((timeouts.tv_sec == 0) && (timeouts.tv_nsec == 0))); +am_Error_e CAmSocketHandler::addTimer(const timespec & timeouts, std::function callback, sh_timerHandle_t& handle, void * userData, const bool repeats) +{ + assert(!((timeouts.tv_sec == 0) && (timeouts.tv_nsec == 0))); - mListTimer.emplace_back(); - sh_timer_s & timerItem = mListTimer.back(); + mListTimer.emplace_back(); + sh_timer_s & timerItem = mListTimer.back(); #ifndef WITH_TIMERFD - //create a new handle for the timer - if (!nextHandle(mSetTimerKeys)) - { - logError("Could not create new timers, too many open!"); - mListTimer.pop_back(); - return (E_NOT_POSSIBLE); - } - //create a new handle for the timer - handle = mSetTimerKeys.lastUsedID; + //create a new handle for the timer + if (!nextHandle(mSetTimerKeys)) + { + logError("Could not create new timers, too many open!"); + mListTimer.pop_back(); + return (E_NOT_POSSIBLE); + } + //create a new handle for the timer + handle = mSetTimerKeys.lastUsedID; - timerItem.countdown = timeouts; - timerItem.callback = callback; - timerItem.userData = userData; + timerItem.countdown = timeouts; + timerItem.callback = callback; + timerItem.userData = userData; - timerItem.handle = handle; + timerItem.handle = handle; - //we add here the time difference between startTime and currenttime, because this time will be substracted later on in timecorrection - timespec currentTime; - clock_gettime(CLOCK_MONOTONIC, ¤tTime); - if (!mDispatchDone)//the mainloop is started - timerItem.countdown = timespecAdd(timeouts, timespecSub(currentTime, mStartTime)); - mListTimer.push_back(timerItem); - mListActiveTimer.push_back(timerItem); - mListActiveTimer.sort(compareCountdown); - return (E_OK); + //we add here the time difference between startTime and currenttime, because this time will be substracted later on in timecorrection + timespec currentTime; + clock_gettime(CLOCK_MONOTONIC, ¤tTime); + if (!mDispatchDone)//the mainloop is started + timerItem.countdown = timespecAdd(timeouts, timespecSub(currentTime, mStartTime)); + mListTimer.push_back(timerItem); + mListActiveTimer.push_back(timerItem); + mListActiveTimer.sort(compareCountdown); + return (E_OK); #else - timerItem.countdown.it_value = timeouts; - if (repeats) - timerItem.countdown.it_interval = timeouts; - else - { - timespec zero; - zero.tv_sec = 0; - zero.tv_nsec = 0; - timerItem.countdown.it_interval = zero; - } - - timerItem.fd = -1; - timerItem.userData = userData; - am_Error_e err = createTimeFD(timerItem.countdown, timerItem.fd); - if (err != E_OK) - { - mListTimer.pop_back(); - return err; - } + timerItem.countdown.it_value = timeouts; + if (repeats) + timerItem.countdown.it_interval = timeouts; + else + { + timespec zero; + zero.tv_sec = 0; + zero.tv_nsec = 0; + timerItem.countdown.it_interval = zero; + } - static auto actionPoll = [](const pollfd pollfd, const sh_pollHandle_t handle, void* userData) - { - uint64_t mExpirations; - if (read(pollfd.fd, &mExpirations, sizeof(uint64_t)) == -1) - { - //error received...try again - read(pollfd.fd, &mExpirations, sizeof(uint64_t)); - } - }; + timerItem.fd = -1; + timerItem.userData = userData; + am_Error_e err = createTimeFD(timerItem.countdown, timerItem.fd); + if (err != E_OK) + { + mListTimer.pop_back(); + return err; + } - err = addFDPoll(timerItem.fd, POLLIN, NULL, actionPoll, [callback](const sh_pollHandle_t handle, void* userData)->bool - { - callback(handle, userData); - return false; - }, - NULL, userData, handle); - if (E_OK == err) - { - timerItem.handle = handle; - } - else + static auto actionPoll = [](const pollfd pollfd, const sh_pollHandle_t handle, void* userData) + { + uint64_t mExpirations; + if (read(pollfd.fd, &mExpirations, sizeof(uint64_t)) == -1) { - mListTimer.pop_back(); + //error received...try again + read(pollfd.fd, &mExpirations, sizeof(uint64_t)); } - return err; -#endif + }; + err = addFDPoll(timerItem.fd, POLLIN, NULL, actionPoll, [callback](const sh_pollHandle_t handle, void* userData)->bool + { + callback(handle, userData); + return false; + }, + NULL, userData, handle); + if (E_OK == err) + { + timerItem.handle = handle; } - - /** - * removes a timer from the list of timers - * @param handle the handle to the timer - * @return E_OK in case of success, E_UNKNOWN if timer was not found. - */ - am_Error_e CAmSocketHandler::removeTimer(const sh_timerHandle_t handle) + else { - assert(handle != 0); + mListTimer.pop_back(); + } + return err; +#endif - //stop the current timer +} + +/** + * removes a timer from the list of timers + * @param handle the handle to the timer + * @return E_OK in case of success, E_UNKNOWN if timer was not found. + */ +am_Error_e CAmSocketHandler::removeTimer(const sh_timerHandle_t handle) +{ + assert(handle != 0); + + //stop the current timer #ifdef WITH_TIMERFD - std::list::iterator it = mListTimer.begin(); - for (; it != mListTimer.end(); ++it) - { - if (it->handle == handle) - break; - } - if (it == mListTimer.end()) - return (E_NON_EXISTENT); + std::list::iterator it = mListTimer.begin(); + for (; it != mListTimer.end(); ++it) + { + if (it->handle == handle) + break; + } + if (it == mListTimer.end()) + return (E_NON_EXISTENT); - close(it->fd); - mListTimer.erase(it); - return removeFDPoll(handle); + close(it->fd); + mListTimer.erase(it); + return removeFDPoll(handle); #else - stopTimer(handle); - std::list::iterator it(mListTimer.begin()); - for (; it != mListTimer.end(); ++it) + stopTimer(handle); + std::list::iterator it(mListTimer.begin()); + for (; it != mListTimer.end(); ++it) + { + if (it->handle == handle) { - if (it->handle == handle) - { - it = mListTimer.erase(it); - mSetTimerKeys.pollHandles.erase(handle); - return (E_OK); - } + it = mListTimer.erase(it); + mSetTimerKeys.pollHandles.erase(handle); + return (E_OK); } - return (E_UNKNOWN); -#endif } + return (E_UNKNOWN); +#endif +} - /** - * restarts a timer and updates with a new interva - * @param handle handle to the timer - * @param timeouts new timout time - * @return E_OK on success, E_NON_EXISTENT if the handle was not found - */ - am_Error_e CAmSocketHandler::updateTimer(const sh_timerHandle_t handle, const timespec & timeouts) - { +/** + * restarts a timer and updates with a new interva + * @param handle handle to the timer + * @param timeouts new timout time + * @return E_OK on success, E_NON_EXISTENT if the handle was not found + */ +am_Error_e CAmSocketHandler::updateTimer(const sh_timerHandle_t handle, const timespec & timeouts) +{ #ifdef WITH_TIMERFD - std::list::iterator it = mListTimer.begin(); - for (; it != mListTimer.end(); ++it) - { - if (it->handle == handle) - break; - } - if (it == mListTimer.end()) - return (E_NON_EXISTENT); + std::list::iterator it = mListTimer.begin(); + for (; it != mListTimer.end(); ++it) + { + if (it->handle == handle) + break; + } + if (it == mListTimer.end()) + return (E_NON_EXISTENT); - if (it->countdown.it_interval.tv_nsec != 0 || it->countdown.it_interval.tv_sec != 0) - it->countdown.it_interval = timeouts; - it->countdown.it_value = timeouts; + if (it->countdown.it_interval.tv_nsec != 0 || it->countdown.it_interval.tv_sec != 0) + it->countdown.it_interval = timeouts; + it->countdown.it_value = timeouts; - if (!fdIsValid(it->fd)) - { - am_Error_e err = createTimeFD(it->countdown, it->fd); - if (err != E_OK) - return err; - } - else + if (!fdIsValid(it->fd)) + { + am_Error_e err = createTimeFD(it->countdown, it->fd); + if (err != E_OK) + return err; + } + else + { + if (timerfd_settime(it->fd, 0, &it->countdown, NULL)) { - if (timerfd_settime(it->fd, 0, &it->countdown, NULL)) - { - logError("Failed to set timer duration"); - return E_NOT_POSSIBLE; - } + logError("Failed to set timer duration"); + return E_NOT_POSSIBLE; } + } #else - //update the mList .... - sh_timer_s timerItem; - std::list::iterator it(mListTimer.begin()), activeIt(mListActiveTimer.begin()); - bool found(false); - for (; it != mListTimer.end(); ++it) + //update the mList .... + sh_timer_s timerItem; + std::list::iterator it(mListTimer.begin()), activeIt(mListActiveTimer.begin()); + bool found(false); + for (; it != mListTimer.end(); ++it) + { + if (it->handle == handle) { - if (it->handle == handle) - { - it->countdown = timeouts; - timerItem = *it; - found = true; - break; - } + it->countdown = timeouts; + timerItem = *it; + found = true; + break; } - if (!found) - return (E_NON_EXISTENT); + } + if (!found) + return (E_NON_EXISTENT); - found = false; + found = false; - //we add here the time difference between startTime and currenttime, because this time will be substracted later on in timecorrection - timespec currentTime, timeoutsCorrected; - currentTime.tv_nsec=timeoutsCorrected.tv_nsec=0; - currentTime.tv_sec=timeoutsCorrected.tv_sec=0; - clock_gettime(CLOCK_MONOTONIC, ¤tTime); - if (!mDispatchDone)//the mainloop is started - timeoutsCorrected = timespecAdd(timeouts, timespecSub(currentTime, mStartTime)); + //we add here the time difference between startTime and currenttime, because this time will be substracted later on in timecorrection + timespec currentTime, timeoutsCorrected; + currentTime.tv_nsec=timeoutsCorrected.tv_nsec=0; + currentTime.tv_sec=timeoutsCorrected.tv_sec=0; + clock_gettime(CLOCK_MONOTONIC, ¤tTime); + if (!mDispatchDone)//the mainloop is started + timeoutsCorrected = timespecAdd(timeouts, timespecSub(currentTime, mStartTime)); - for (; activeIt != mListActiveTimer.end(); ++activeIt) + for (; activeIt != mListActiveTimer.end(); ++activeIt) + { + if (activeIt->handle == handle) { - if (activeIt->handle == handle) - { - activeIt->countdown = timeoutsCorrected; - found = true; - break; - } + activeIt->countdown = timeoutsCorrected; + found = true; + break; } + } - if (!found) - timerItem.countdown = timeoutsCorrected; - mListActiveTimer.push_back(timerItem); + if (!found) + timerItem.countdown = timeoutsCorrected; + mListActiveTimer.push_back(timerItem); - mListActiveTimer.sort(compareCountdown); + mListActiveTimer.sort(compareCountdown); #endif - return (E_OK); - } + return (E_OK); +} - /** - * restarts a timer with the original value - * @param handle - * @return E_OK on success, E_NON_EXISTENT if the handle was not found - */ - am_Error_e CAmSocketHandler::restartTimer(const sh_timerHandle_t handle) - { +/** + * restarts a timer with the original value + * @param handle + * @return E_OK on success, E_NON_EXISTENT if the handle was not found + */ +am_Error_e CAmSocketHandler::restartTimer(const sh_timerHandle_t handle) +{ #ifdef WITH_TIMERFD - std::list::iterator it = mListTimer.begin(); - for (; it != mListTimer.end(); ++it) - { - if (it->handle == handle) - break; - } - if (it == mListTimer.end()) - return (E_NON_EXISTENT); + std::list::iterator it = mListTimer.begin(); + for (; it != mListTimer.end(); ++it) + { + if (it->handle == handle) + break; + } + if (it == mListTimer.end()) + return (E_NON_EXISTENT); - if (!fdIsValid(it->fd)) - { - am_Error_e err = createTimeFD(it->countdown, it->fd); - if (err != E_OK) - return err; - } - else + if (!fdIsValid(it->fd)) + { + am_Error_e err = createTimeFD(it->countdown, it->fd); + if (err != E_OK) + return err; + } + else + { + if (timerfd_settime(it->fd, 0, &it->countdown, NULL)) { - if (timerfd_settime(it->fd, 0, &it->countdown, NULL)) - { - logError("Failed to set timer duration"); - return E_NOT_POSSIBLE; - } + logError("Failed to set timer duration"); + return E_NOT_POSSIBLE; } + } #else - sh_timer_s timerItem; //!::iterator it(mListTimer.begin()), activeIt(mListActiveTimer.begin()); - bool found(false); - for (; it != mListTimer.end(); ++it) + sh_timer_s timerItem; //!::iterator it(mListTimer.begin()), activeIt(mListActiveTimer.begin()); + bool found(false); + for (; it != mListTimer.end(); ++it) + { + if (it->handle == handle) { - if (it->handle == handle) - { - timerItem = *it; - found = true; - break; - } + timerItem = *it; + found = true; + break; } - if (!found) - return (E_NON_EXISTENT); + } + if (!found) + return (E_NON_EXISTENT); - found = false; + found = false; - //we add here the time difference between startTime and currenttime, because this time will be substracted later on in timecorrection - timespec currentTime, timeoutsCorrected; - clock_gettime(CLOCK_MONOTONIC, ¤tTime); - if (!mDispatchDone)//the mainloop is started - { - timeoutsCorrected = timespecAdd(timerItem.countdown, timespecSub(currentTime, mStartTime)); - timerItem.countdown = timeoutsCorrected; - } + //we add here the time difference between startTime and currenttime, because this time will be substracted later on in timecorrection + timespec currentTime, timeoutsCorrected; + clock_gettime(CLOCK_MONOTONIC, ¤tTime); + if (!mDispatchDone)//the mainloop is started + { + timeoutsCorrected = timespecAdd(timerItem.countdown, timespecSub(currentTime, mStartTime)); + timerItem.countdown = timeoutsCorrected; + } - for (; activeIt != mListActiveTimer.end(); ++activeIt) + for (; activeIt != mListActiveTimer.end(); ++activeIt) + { + if (activeIt->handle == handle) { - if (activeIt->handle == handle) - { - activeIt->countdown = timerItem.countdown; - found = true; - break; - } + activeIt->countdown = timerItem.countdown; + found = true; + break; } + } - if (!found) - mListActiveTimer.push_back(timerItem); + if (!found) + mListActiveTimer.push_back(timerItem); - mListActiveTimer.sort(compareCountdown); + mListActiveTimer.sort(compareCountdown); #endif - return (E_OK); - } + return (E_OK); +} - /** - * stops a timer - * @param handle - * @return E_OK on success, E_NON_EXISTENT if the handle was not found - */ - am_Error_e CAmSocketHandler::stopTimer(const sh_timerHandle_t handle) - { +/** + * stops a timer + * @param handle + * @return E_OK on success, E_NON_EXISTENT if the handle was not found + */ +am_Error_e CAmSocketHandler::stopTimer(const sh_timerHandle_t handle) +{ #ifdef WITH_TIMERFD - std::list::iterator it = mListTimer.begin(); - for (; it != mListTimer.end(); ++it) - { - if (it->handle == handle) - break; - } - if (it == mListTimer.end()) - return (E_NON_EXISTENT); + std::list::iterator it = mListTimer.begin(); + for (; it != mListTimer.end(); ++it) + { + if (it->handle == handle) + break; + } + if (it == mListTimer.end()) + return (E_NON_EXISTENT); - itimerspec countdown = it->countdown; - countdown.it_value.tv_nsec = 0; - countdown.it_value.tv_sec = 0; + itimerspec countdown = it->countdown; + countdown.it_value.tv_nsec = 0; + countdown.it_value.tv_sec = 0; - if (timerfd_settime(it->fd, 0, &countdown, NULL)) - { - logError("Failed to set timer duration"); - return E_NOT_POSSIBLE; - } - return (E_OK); + if (timerfd_settime(it->fd, 0, &countdown, NULL)) + { + logError("Failed to set timer duration"); + return E_NOT_POSSIBLE; + } + return (E_OK); #else - //go through the list and remove the timer with the handle - std::list::iterator it(mListActiveTimer.begin()); - for (; it != mListActiveTimer.end(); ++it) + //go through the list and remove the timer with the handle + std::list::iterator it(mListActiveTimer.begin()); + for (; it != mListActiveTimer.end(); ++it) + { + if (it->handle == handle) { - if (it->handle == handle) - { - it = mListActiveTimer.erase(it); - return (E_OK); - } + it = mListActiveTimer.erase(it); + return (E_OK); } - return (E_NON_EXISTENT); -#endif } + return (E_NON_EXISTENT); +#endif +} - /** - * updates the eventFlags of a poll - * @param handle - * @param events - * @return @return E_OK on succsess, E_NON_EXISTENT if fd was not found - */ - am_Error_e CAmSocketHandler::updateEventFlags(const sh_pollHandle_t handle, const short events) - { - VectorListPoll_t::iterator iterator = mListPoll.begin(); +/** + * updates the eventFlags of a poll + * @param handle + * @param events + * @return @return E_OK on succsess, E_NON_EXISTENT if fd was not found + */ +am_Error_e CAmSocketHandler::updateEventFlags(const sh_pollHandle_t handle, const short events) +{ + VectorListPoll_t::iterator iterator = mListPoll.begin(); - for (; iterator != mListPoll.end(); ++iterator) + for (; iterator != mListPoll.end(); ++iterator) + { + if (iterator->handle == handle) { - if (iterator->handle == handle) - { - iterator->pollfdValue.events = events; - mRecreatePollfds = true; - return (E_OK); - } + iterator->pollfdValue.events = events; + mRecreatePollfds = true; + return (E_OK); } - return (E_UNKNOWN); } + return (E_UNKNOWN); +} - /** - * checks if a filedescriptor is validCAmShSubstractTime - * @param fd the filedescriptor - * @return true if the fd is valid - */ - bool CAmSocketHandler::fdIsValid(const int fd) const - { - return (fcntl(fd, F_GETFL) != -1 || errno != EBADF); - } +/** + * checks if a filedescriptor is validCAmShSubstractTime + * @param fd the filedescriptor + * @return true if the fd is valid + */ +bool CAmSocketHandler::fdIsValid(const int fd) const +{ + return (fcntl(fd, F_GETFL) != -1 || errno != EBADF); +} #ifndef WITH_TIMERFD - /** - * timer is up. - */ - void CAmSocketHandler::timerUp() +/** + * timer is up. + */ +void CAmSocketHandler::timerUp() +{ + //find out the timedifference to starttime + static timespec currentTime, diffTime; + clock_gettime(CLOCK_MONOTONIC, ¤tTime); + diffTime = timespecSub(currentTime, mStartTime); + + static auto countdownUp = [&](const sh_timer_s& row)->bool { - //find out the timedifference to starttime - static timespec currentTime, diffTime; - clock_gettime(CLOCK_MONOTONIC, ¤tTime); - diffTime = timespecSub(currentTime, mStartTime); + timespec sub = timespecSub(row.countdown, diffTime); + if (sub.tv_nsec == 0 && sub.tv_sec == 0) + return (true); + return (false); + }; - static auto countdownUp = [&](const sh_timer_s& row)->bool - { - timespec sub = timespecSub(row.countdown, diffTime); - if (sub.tv_nsec == 0 && sub.tv_sec == 0) - return (true); - return (false); - }; + //now we need to substract the diffTime from all timers and see if they are up + std::list::reverse_iterator overflowIter = std::find_if(mListActiveTimer.rbegin(), mListActiveTimer.rend(), countdownUp); - //now we need to substract the diffTime from all timers and see if they are up - std::list::reverse_iterator overflowIter = std::find_if(mListActiveTimer.rbegin(), mListActiveTimer.rend(), countdownUp); + //copy all fired timers into a list + std::vector tempList(overflowIter, mListActiveTimer.rend()); - //copy all fired timers into a list - std::vector tempList(overflowIter, mListActiveTimer.rend()); + //erase all fired timers + std::list::iterator it(overflowIter.base()); + mListActiveTimer.erase(mListActiveTimer.begin(), it); - //erase all fired timers - std::list::iterator it(overflowIter.base()); - mListActiveTimer.erase(mListActiveTimer.begin(), it); + //call the callbacks for the timers + std::for_each(tempList.begin(), tempList.end(), CAmSocketHandler::callTimer); +} - //call the callbacks for the timers - std::for_each(tempList.begin(), tempList.end(), CAmSocketHandler::callTimer); - } +/** + * correct timers and fire the ones who are up + */ +void CAmSocketHandler::timerCorrection() +{ + //get the current time and calculate the correction value + static timespec currentTime, correctionTime; + clock_gettime(CLOCK_MONOTONIC, ¤tTime); + correctionTime = timespecSub(currentTime, mStartTime); + mStartTime = currentTime; - /** - * correct timers and fire the ones who are up - */ - void CAmSocketHandler::timerCorrection() + static auto countdownZero = [](const sh_timer_s& row)->bool { - //get the current time and calculate the correction value - static timespec currentTime, correctionTime; - clock_gettime(CLOCK_MONOTONIC, ¤tTime); - correctionTime = timespecSub(currentTime, mStartTime); - mStartTime = currentTime; - - static auto countdownZero = [](const sh_timer_s& row)->bool - { - if (row.countdown.tv_nsec == 0 && row.countdown.tv_sec == 0) - return (true); - return (false); - }; + if (row.countdown.tv_nsec == 0 && row.countdown.tv_sec == 0) + return (true); + return (false); + }; - static auto substractTime = [&](sh_timer_s& t) - { - t.countdown = timespecSub(t.countdown, correctionTime); - }; + static auto substractTime = [&](sh_timer_s& t) + { + t.countdown = timespecSub(t.countdown, correctionTime); + }; - if (!mListActiveTimer.empty()) - { + if (!mListActiveTimer.empty()) + { - //subtract the correction value from all items in the list - std::for_each(mListActiveTimer.begin(), mListActiveTimer.end(), substractTime); + //subtract the correction value from all items in the list + std::for_each(mListActiveTimer.begin(), mListActiveTimer.end(), substractTime); - //find the last occurrence of zero -> timer overflowed - std::list::reverse_iterator overflowIter = std::find_if(mListActiveTimer.rbegin(), mListActiveTimer.rend(), countdownZero); + //find the last occurrence of zero -> timer overflowed + std::list::reverse_iterator overflowIter = std::find_if(mListActiveTimer.rbegin(), mListActiveTimer.rend(), countdownZero); - //only if a timer overflowed - if (overflowIter != mListActiveTimer.rend()) - { - //copy all timers that need to be called to a new list - std::vector tempList(overflowIter, mListActiveTimer.rend()); + //only if a timer overflowed + if (overflowIter != mListActiveTimer.rend()) + { + //copy all timers that need to be called to a new list + std::vector tempList(overflowIter, mListActiveTimer.rend()); - //erase all fired timers - std::list::iterator it(overflowIter.base()); - mListActiveTimer.erase(mListActiveTimer.begin(), it); + //erase all fired timers + std::list::iterator it(overflowIter.base()); + mListActiveTimer.erase(mListActiveTimer.begin(), it); - //call the callbacks for the timers - std::for_each(tempList.begin(), tempList.end(), CAmSocketHandler::callTimer); - } + //call the callbacks for the timers + std::for_each(tempList.begin(), tempList.end(), CAmSocketHandler::callTimer); } } +} #endif - /** - * prepare for poll - */ - void CAmSocketHandler::prepare(am::CAmSocketHandler::sh_poll_s& row) - { - if (row.prepareCB) - { - try - { - row.prepareCB(row.handle, row.userData); - } catch (std::exception& e) - { - logError("Sockethandler: Exception in Preparecallback,caught", e.what()); - } - } - } - - /** - * fire callback - */ - void CAmSocketHandler::fire(sh_poll_s& a) +/** + * prepare for poll + */ +void CAmSocketHandler::prepare(am::CAmSocketHandler::sh_poll_s& row) +{ + if (row.prepareCB) { try { - a.firedCB(a.pollfdValue, a.handle, a.userData); + row.prepareCB(row.handle, row.userData); } catch (std::exception& e) { logError("Sockethandler: Exception in Preparecallback,caught", e.what()); } } +} - /** - * should disptach - */ - bool CAmSocketHandler::noDispatching(const sh_poll_s& a) +/** + * fire callback + */ +void CAmSocketHandler::fire(sh_poll_s& a) +{ + try { - //remove from list of there is no checkCB - if (nullptr == a.checkCB) - return (true); - return (!a.checkCB(a.handle, a.userData)); - } - - /** - * disptach - */ - bool CAmSocketHandler::dispatchingFinished(const sh_poll_s& a) + a.firedCB(a.pollfdValue, a.handle, a.userData); + } catch (std::exception& e) { - //remove from list of there is no dispatchCB - if (nullptr == a.dispatchCB) - return (true); - return (!a.dispatchCB(a.handle, a.userData)); + logError("Sockethandler: Exception in Preparecallback,caught", e.what()); } +} - /** - * event triggered - */ - bool CAmSocketHandler::eventFired(const pollfd& a) - { - return (a.revents == 0 ? false : true); - } +/** + * should disptach + */ +bool CAmSocketHandler::noDispatching(const sh_poll_s& a) +{ + //remove from list of there is no checkCB + if (nullptr == a.checkCB) + return (true); + return (!a.checkCB(a.handle, a.userData)); +} - /** - * is used to set the pointer for the ppoll command - * @param buffertime - * @return - */ - inline timespec* CAmSocketHandler::insertTime(timespec& buffertime) - { +/** + * disptach + */ +bool CAmSocketHandler::dispatchingFinished(const sh_poll_s& a) +{ + //remove from list of there is no dispatchCB + if (nullptr == a.dispatchCB) + return (true); + return (!a.dispatchCB(a.handle, a.userData)); +} + +/** + * event triggered + */ +bool CAmSocketHandler::eventFired(const pollfd& a) +{ + return (a.revents == 0 ? false : true); +} + +/** + * is used to set the pointer for the ppoll command + * @param buffertime + * @return + */ +inline timespec* CAmSocketHandler::insertTime(timespec& buffertime) +{ #ifndef WITH_TIMERFD - if (!mListActiveTimer.empty()) - { - buffertime = mListActiveTimer.front().countdown; - return (&buffertime); - } - else + if (!mListActiveTimer.empty()) + { + buffertime = mListActiveTimer.front().countdown; + return (&buffertime); + } + else #endif - { - return (NULL); - } + { + return (NULL); } +} #ifdef WITH_TIMERFD - am_Error_e CAmSocketHandler::createTimeFD(const itimerspec & timeouts, int & fd) +am_Error_e CAmSocketHandler::createTimeFD(const itimerspec & timeouts, int & fd) +{ + fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); + if (fd <= 0) { - fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); - if (fd <= 0) - { - logError("Failed to create timer"); - return E_NOT_POSSIBLE; - } + logError("Failed to create timer"); + return E_NOT_POSSIBLE; + } - if (timerfd_settime(fd, 0, &timeouts, NULL)) - { - logError("Failed to set timer duration"); - return E_NOT_POSSIBLE; - } - return E_OK; + if (timerfd_settime(fd, 0, &timeouts, NULL)) + { + logError("Failed to set timer duration"); + return E_NOT_POSSIBLE; } + return E_OK; +} #endif - void CAmSocketHandler::callTimer(sh_timer_s& a) +void CAmSocketHandler::callTimer(sh_timer_s& a) +{ + try { - try - { - a.callback(a.handle, a.userData); - } catch (std::exception& e) - { - logError("Sockethandler: Exception in Timercallback,caught", e.what()); - } + a.callback(a.handle, a.userData); + } catch (std::exception& e) + { + logError("Sockethandler: Exception in Timercallback,caught", e.what()); } +} - bool CAmSocketHandler::nextHandle(sh_identifier_s & handle) +bool CAmSocketHandler::nextHandle(sh_identifier_s & handle) +{ + //create a new handle for the poll + const sh_pollHandle_t lastHandle(handle.lastUsedID); + do { - //create a new handle for the poll - const sh_pollHandle_t lastHandle(handle.lastUsedID); - do + ++handle.lastUsedID; + if (handle.lastUsedID == handle.limit) { - ++handle.lastUsedID; - if (handle.lastUsedID == handle.limit) - { - handle.lastUsedID = 1; - } - if (handle.lastUsedID == lastHandle) - { - logError("Could not create new polls, too many open!"); - return (false); - } + handle.lastUsedID = 1; + } + if (handle.lastUsedID == lastHandle) + { + logError("Could not create new polls, too many open!"); + return (false); + } - } while (handle.pollHandles.find(handle.lastUsedID) != handle.pollHandles.end()); + } while (handle.pollHandles.find(handle.lastUsedID) != handle.pollHandles.end()); - handle.pollHandles.insert(handle.lastUsedID); + handle.pollHandles.insert(handle.lastUsedID); - return (true); - } + return (true); +} } diff --git a/AudioManagerUtilities/test/AmSerializerTest/CMakeLists.txt b/AudioManagerUtilities/test/AmSerializerTest/CMakeLists.txt index 3e89267..e0d2287 100644 --- a/AudioManagerUtilities/test/AmSerializerTest/CMakeLists.txt +++ b/AudioManagerUtilities/test/AmSerializerTest/CMakeLists.txt @@ -33,6 +33,7 @@ ADD_EXECUTABLE(AmSerializerTest ${Socket_SRCS_CXX}) TARGET_LINK_LIBRARIES(AmSerializerTest ${GTEST_LIBRARIES} ${GMOCK_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} AudioManagerUtilities ) diff --git a/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp b/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp index af21f90..ecd38fe 100644 --- a/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp +++ b/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp @@ -48,6 +48,22 @@ static const char * TEST_SOCKET_DATA_FINAL = "finish!"; static const std::chrono::time_point TP_ZERO; + +MockIAmSignalHandler *pMockSignalHandler = NULL; +static void signalHandler(int sig, siginfo_t *siginfo, void *context) +{ + (void) sig; + (void) siginfo; + (void) context; + + if(pMockSignalHandler!=NULL) + pMockSignalHandler->signalHandler(sig, siginfo, context); + +#ifdef ENABLED_SOCKETHANDLER_TEST_OUTPUT + std::cout<<"signal handler was called with signal " << sig << std::endl; +#endif +} + CAmSocketHandlerTest::CAmSocketHandlerTest() { } @@ -227,7 +243,7 @@ TEST(CAmSocketHandlerTest, timersOneshot) #ifndef WITH_TIMERFD ASSERT_EQ(handle, 1); #else - ASSERT_EQ(handle, 3); + ASSERT_EQ(handle, 2); #endif EXPECT_CALL(testCallback1,timerCallback(handle,&userData)).Times(1); @@ -240,7 +256,7 @@ TEST(CAmSocketHandlerTest, timersOneshot) #ifndef WITH_TIMERFD ASSERT_EQ(handle, 2); #else - ASSERT_EQ(handle, 4); + ASSERT_EQ(handle, 3); #endif EXPECT_CALL(testCallback4,timerCallback(handle,NULL)).Times(1); myHandler.start_listenting(); @@ -269,7 +285,7 @@ TEST(CAmSocketHandlerTest, timersStop) #ifndef WITH_TIMERFD ASSERT_EQ(handle, 1); #else - ASSERT_EQ(handle, 3); + ASSERT_EQ(handle, 2); #endif EXPECT_CALL(testCallback1,timerCallback(handle,&userData)).Times(4); @@ -282,7 +298,7 @@ TEST(CAmSocketHandlerTest, timersStop) #ifndef WITH_TIMERFD ASSERT_EQ(handle, 2); #else - ASSERT_EQ(handle, 4); + ASSERT_EQ(handle, 3); #endif EXPECT_CALL(testCallback4,timerCallback(handle,NULL)).Times(1); myHandler.start_listenting(); @@ -312,7 +328,7 @@ TEST(CAmSocketHandlerTest, timersGeneral) #ifndef WITH_TIMERFD ASSERT_EQ(handle, 1); #else - ASSERT_EQ(handle, 3); + ASSERT_EQ(handle, 2); #endif EXPECT_CALL(testCallback1,timerCallback(handle,&userData)).Times(4); //+1 because of measurment @@ -325,7 +341,7 @@ TEST(CAmSocketHandlerTest, timersGeneral) #ifndef WITH_TIMERFD ASSERT_EQ(handle, 2); #else - ASSERT_EQ(handle, 4); + ASSERT_EQ(handle, 3); #endif EXPECT_CALL(testCallback4,timerCallback(handle,NULL)).Times(1); myHandler.start_listenting(); @@ -356,7 +372,7 @@ TEST(CAmSocketHandlerTest,playWithTimers) #ifndef WITH_TIMERFD ASSERT_EQ(handle, 1); #else - ASSERT_EQ(handle, 3); + ASSERT_EQ(handle, 2); #endif EXPECT_CALL(testCallback1,timerCallback(handle,NULL)).Times(AnyNumber()); @@ -364,7 +380,7 @@ TEST(CAmSocketHandlerTest,playWithTimers) #ifndef WITH_TIMERFD ASSERT_EQ(handle, 2); #else - ASSERT_EQ(handle, 4); + ASSERT_EQ(handle, 3); #endif EXPECT_CALL(testCallback2,timerCallback(handle,NULL)).Times(AnyNumber()); @@ -372,7 +388,7 @@ TEST(CAmSocketHandlerTest,playWithTimers) #ifndef WITH_TIMERFD ASSERT_EQ(handle, 3); #else - ASSERT_EQ(handle, 5); + ASSERT_EQ(handle, 4); #endif EXPECT_CALL(testCallback3,timerCallback(handle,NULL)).Times(2); //+1 because of measurment @@ -380,64 +396,82 @@ TEST(CAmSocketHandlerTest,playWithTimers) #ifndef WITH_TIMERFD ASSERT_EQ(handle, 4); #else - ASSERT_EQ(handle, 6); + ASSERT_EQ(handle, 5); #endif EXPECT_CALL(testCallback4,timerCallback(handle,NULL)).Times(1); myHandler.start_listenting(); } -TEST(CAmSocketHandlerTest, signalHandler) + + +TEST(CAmSocketHandlerTest, signalHandlerPrimaryPlusSecondary) { + pMockSignalHandler = new MockIAmSignalHandler; CAmSocketHandler myHandler; ASSERT_FALSE(myHandler.fatalErrorOccurred()); + ASSERT_TRUE(myHandler.listenToSignals({SIGHUP})==E_OK); + ASSERT_TRUE(myHandler.listenToSignals({SIGHUP, SIGTERM, SIGCHLD})==E_OK); sh_pollHandle_t signalHandler1, signalHandler2; - MockIAmSignalHandler mock; + std::string userData = "User data"; - myHandler.addSignalHandler([&](const sh_pollHandle_t handle, const signalfd_siginfo & info, void* userData) - { - unsigned sig = info.ssi_signo; - mock.signalHandlerAction(handle, sig, userData); + +// critical signals are registered here: + struct sigaction signalAction; + memset(&signalAction, '\0', sizeof(signalAction)); + signalAction.sa_sigaction = &signalHandler; + signalAction.sa_flags = SA_RESETHAND | SA_NODEFER| SA_SIGINFO; + sigaction(SIGINT, &signalAction, NULL); + sigaction(SIGQUIT, &signalAction, NULL); + + myHandler.addSignalHandler([&](const sh_pollHandle_t handle, const signalfd_siginfo & info, void* userData) + { + unsigned sig = info.ssi_signo; + pMockSignalHandler->signalHandlerAction(handle, sig, userData); #ifdef ENABLED_SOCKETHANDLER_TEST_OUTPUT - unsigned user = info.ssi_uid; - std::cout<<"signal handler was called from user "<< user << " with signal " << sig << std::endl; + unsigned user = info.ssi_uid; + std::cout<<"signal handler was called from user "<< user << " with signal " << sig << std::endl; #endif - }, signalHandler1, &userData); - ASSERT_EQ(signalHandler1, 1); - myHandler.addSignalHandler([&](const sh_pollHandle_t handle, const signalfd_siginfo & info, void* userData) - { - unsigned sig = info.ssi_signo; - mock.signalHandlerAction(handle, sig, userData); - #ifdef ENABLED_SOCKETHANDLER_TEST_OUTPUT - unsigned user = info.ssi_uid; - std::cout<<"signal handler was called from user "<< user << " with signal " << sig << std::endl; - #endif - }, signalHandler2, &userData); - ASSERT_EQ(signalHandler2, 2); + }, signalHandler1, &userData); + ASSERT_EQ(signalHandler1, 1); + myHandler.addSignalHandler([&](const sh_pollHandle_t handle, const signalfd_siginfo & info, void* userData) + { + unsigned sig = info.ssi_signo; + pMockSignalHandler->signalHandlerAction(handle, sig, userData); +#ifdef ENABLED_SOCKETHANDLER_TEST_OUTPUT + unsigned user = info.ssi_uid; + std::cout<<"signal handler was called from user "<< user << " with signal " << sig << std::endl; +#endif + }, signalHandler2, &userData); + ASSERT_EQ(signalHandler2, 2); timespec timeout4; timeout4.tv_nsec = 200000000; timeout4.tv_sec = 0; - std::set signals; - signals.insert(SIGHUP); - signals.insert(SIGINT); - signals.insert(SIGTERM); - signals.insert(SIGQUIT); + std::set secondarySignals; + secondarySignals.insert({SIGHUP,SIGTERM, SIGCHLD}); + std::set primarySignals({SIGQUIT,SIGINT}); + std::set signals(primarySignals); + signals.insert(secondarySignals.begin(), secondarySignals.end()); CAmTimerSignalHandler testCallback4(&myHandler, timeout4, signals); sh_timerHandle_t handle; myHandler.addTimer(timeout4, &testCallback4.pTimerCallback, handle, NULL, true); #ifndef WITH_TIMERFD - ASSERT_EQ(handle, 1); + ASSERT_EQ(handle, 1); #else - ASSERT_EQ(handle, 3); + ASSERT_EQ(handle, 3); #endif EXPECT_CALL(testCallback4,timerCallback(handle,NULL)).Times(signals.size()+1); - for(auto it: signals) - EXPECT_CALL(mock,signalHandlerAction(signalHandler1,it,&userData)).Times(1); - for(auto it: signals) - EXPECT_CALL(mock,signalHandlerAction(signalHandler2,it,&userData)).Times(1); + for(auto it: secondarySignals) + EXPECT_CALL(*pMockSignalHandler,signalHandlerAction(signalHandler1,it,&userData)).Times(1); + for(auto it: secondarySignals) + EXPECT_CALL(*pMockSignalHandler,signalHandlerAction(signalHandler2,it,&userData)).Times(1); + for(auto it: primarySignals) + EXPECT_CALL(*pMockSignalHandler,signalHandler(it,_,_)).Times(1); + myHandler.start_listenting(); + delete pMockSignalHandler; } TEST(CAmSocketHandlerTest,playWithUNIXSockets) diff --git a/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.h b/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.h index d38f8c1..ba2bf51 100644 --- a/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.h +++ b/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.h @@ -54,6 +54,7 @@ namespace am { } virtual void signalHandlerAction(const sh_pollHandle_t handle, const unsigned sig, void* userData)=0; + virtual void signalHandler(int sig, siginfo_t *siginfo, void *context)=0; }; class IAmSocketHandlerCb @@ -78,6 +79,7 @@ namespace am { public: MOCK_METHOD3(signalHandlerAction, void (const sh_pollHandle_t handle, const unsigned sig, void* userData)); + MOCK_METHOD3(signalHandler, void(int sig, siginfo_t *siginfo, void *context)); }; class MockSocketHandlerCb: public IAmSocketHandlerCb diff --git a/AudioManagerUtilities/test/AmSocketHandlerTest/CMakeLists.txt b/AudioManagerUtilities/test/AmSocketHandlerTest/CMakeLists.txt index 8f0c9e6..5e5b9e1 100644 --- a/AudioManagerUtilities/test/AmSocketHandlerTest/CMakeLists.txt +++ b/AudioManagerUtilities/test/AmSocketHandlerTest/CMakeLists.txt @@ -33,6 +33,7 @@ ADD_EXECUTABLE(AmSocketHandlerTest ${Socket_SRCS_CXX}) TARGET_LINK_LIBRARIES(AmSocketHandlerTest ${GTEST_LIBRARIES} ${GMOCK_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} AudioManagerUtilities ) diff --git a/CMakeLists.txt b/CMakeLists.txt index b89daa1..5c70c61 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -141,6 +141,7 @@ if(WITH_TESTS) #check if we can find the google stuff pkg_check_modules (GTEST "gtest >= 1.6.0") pkg_check_modules (GMOCK "gmock >= 1.6.0") + find_package (Threads) if (NOT("${GTEST_FOUND}" AND "${GMOCK_FOUND}")) message (STATUS "Building and installing with shipped sources") add_subdirectory(googleMock) diff --git a/docs/main_8cpp_source.html b/docs/main_8cpp_source.html index 9b9df41..0c55aa5 100644 --- a/docs/main_8cpp_source.html +++ b/docs/main_8cpp_source.html @@ -279,7 +279,7 @@ $(document).ready(function(){initNavTree('main_8cpp_source.html','');});
204  switch (sig)
205  {
206  /*ctl +c lets call direct controllerRundown, because we might be blocked at the moment.
-
207  But there is the risk of interrupting something important */https://asc.bmwgroup.net/wiki/display/MGUROTO/Lastest+and+greatest
+
207  But there is the risk of interrupting something important */
208  case SIGINT:
210  break;
-- cgit v1.2.1