From c1cd0d398ee0c25b5af6e4ff96b9991a1b24959d Mon Sep 17 00:00:00 2001 From: Ingo Huerner Date: Thu, 6 Apr 2017 14:11:59 +0200 Subject: Replaced sem_wait with sem_timedwait in pers_lldb_open and pers_lldb_close with 5 sec timeout --- inc/protected/persComErrors.h | 1 + src/key-value-store/pers_low_level_db_access.c | 17 +++- test/test_pco_key_value_store.c | 108 ++++++++++++++++++++++--- 3 files changed, 114 insertions(+), 12 deletions(-) diff --git a/inc/protected/persComErrors.h b/inc/protected/persComErrors.h index 34bf729..806fbf2 100644 --- a/inc/protected/persComErrors.h +++ b/inc/protected/persComErrors.h @@ -56,6 +56,7 @@ extern "C" #define PERS_COM_ERR_OUT_OF_MEMORY (PERS_COM_ERROR_CODE - 8) //!< Not enough resources for an opperation #define PERS_COM_ERR_READONLY (PERS_COM_ERROR_CODE - 9) //!< Database was opened in readonly mode and cannot be written +#define PERS_COM_ERR_SEM_WAIT_TIMEOUT (PERS_COM_ERROR_CODE - 10) //!< sem_wait timeout /* IPC specific error codes */ #define PERS_COM_IPC_ERR_PCL_NOT_AVAILABLE (PERS_COM_ERROR_CODE - 255) //!< PCL client not available (application was killed) diff --git a/src/key-value-store/pers_low_level_db_access.c b/src/key-value-store/pers_low_level_db_access.c index cfc5ffc..29f535e 100644 --- a/src/key-value-store/pers_low_level_db_access.c +++ b/src/key-value-store/pers_low_level_db_access.c @@ -67,6 +67,8 @@ DLT_DECLARE_CONTEXT (persComLldbDLTCtx) #define PERS_STATUS_KEY_NOT_IN_CACHE -10 /* /!< key not in cache */ +#define SEM_TIMEDWAIT_TIMEOUT 5 // wait for seconds until sem_timedwait fails + typedef struct { char m_data[PERS_DB_MAX_SIZE_KEY_DATA]; @@ -121,6 +123,8 @@ static const char ListItemsSeparator = '\0'; static lldb_handlers_s g_sHandlers; // initialize to 0 and NULL //static lldb_handlers_s g_sHandlers = { { { 0 } } }; +static struct timespec gSemWaitTimeout; + /* ---------------------- local macros --------------------------------- */ /* ---------------------- local functions --------------------------------- */ @@ -284,10 +288,15 @@ sint_t pers_lldb_open(str_t const* dbPathname, pers_lldb_purpose_e ePurpose, boo } } } - if (-1 == sem_wait(pLldbHandler->kissDb.kdbSem)) + + clock_gettime(CLOCK_REALTIME, &gSemWaitTimeout); + gSemWaitTimeout.tv_sec += SEM_TIMEDWAIT_TIMEOUT; + if(-1 == sem_timedwait(pLldbHandler->kissDb.kdbSem, &gSemWaitTimeout)) { DLT_LOG(persComLldbDLTCtx, DLT_LOG_ERROR, DLT_STRING(__FUNCTION__); DLT_STRING(": sem_wait() in open failed: "), DLT_STRING(strerror(errno))); + + return PERS_COM_ERR_SEM_WAIT_TIMEOUT; } kdbState = KISSDB_open(&pLldbHandler->kissDb, path, openMode, writeMode, HASHTABLE_SLOT_COUNT, keysize, datasize); if (kdbState != 0) @@ -433,10 +442,14 @@ sint_t pers_lldb_close(sint_t handlerDB) bLocked = true; } - if (-1 == sem_wait(db->kdbSem)) + clock_gettime(CLOCK_REALTIME, &gSemWaitTimeout); + gSemWaitTimeout.tv_sec += SEM_TIMEDWAIT_TIMEOUT; + if (-1 == sem_timedwait(db->kdbSem, &gSemWaitTimeout)) // wait for 5 seconds { DLT_LOG(persComLldbDLTCtx, DLT_LOG_ERROR, DLT_STRING(__FUNCTION__); DLT_STRING(": sem_wait() in close failed: "), DLT_STRING(strerror(errno))); + + return PERS_COM_ERR_SEM_WAIT_TIMEOUT; } DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, diff --git a/test/test_pco_key_value_store.c b/test/test_pco_key_value_store.c index cae906b..62b9866 100644 --- a/test/test_pco_key_value_store.c +++ b/test/test_pco_key_value_store.c @@ -29,6 +29,7 @@ #include #include <../inc/protected/persComRct.h> #include <../inc/protected/persComDbAccess.h> +#include <../inc/protected/persComErrors.h> //#include <../test/pers_com_test_base.h> //#include <../test/pers_com_check.h> #include @@ -3315,7 +3316,86 @@ static Suite* persistenceCommonLib_suite() +void* kvdbOpenThread(void* userData) +{ + int ret = -1; + int handle = -1; + const char* threadID = (const char*) userData; + + sleep(1); + printf("- Started thread - read - %s\n", threadID); + + printf("- do => persComDbOpen\n"); + handle = persComDbOpen("/tmp/semlockTimeoutTest.db", 0x1); //create test.db if not present (cached) + printf("- do <= persComDbOpen\n"); + + if(handle >= 0 ) + { + ret = persComDbClose(handle); + } + else if(handle == PERS_COM_ERR_SEM_WAIT_TIMEOUT) + { + printf("persComDbClose - sem_wait timedout => test PASSED\n"); + } + else + { + printf("persComDbClose - common error: %d\n", handle); + } + + printf("- End - thread: %d \n", handle); + pthread_exit(0); +} + + +void* semBlockingThread(void* userData) +{ + int sleepSec = 10; + sem_t* semHandle; + const char* threadID = (const char*) userData; + + printf("# Started thread - read - %s - do sem_open\n", threadID); + + semHandle = sem_open("_tmp_semlockTimeoutTest_db-sem", O_CREAT | O_EXCL, 0644, 1); + + printf("# Do sem_wait\n"); + sem_wait(semHandle); + + printf("# Now sleep %d seconds, and block persComDbOpen call from other thread\n", sleepSec); + sleep(sleepSec); + + printf("# Do sem_post\n"); + sem_post(semHandle); + + pthread_exit(0); +} + + + +void doSemLockTimeoutTest() +{ + pthread_t threadInfoFirst, threadInfoSecond; + + if(pthread_create(&threadInfoFirst, NULL, semBlockingThread, "Thread Blocking") != -1) + { + (void)pthread_setname_np(threadInfoFirst, "Blocking"); + } + + if(pthread_create(&threadInfoSecond, NULL, kvdbOpenThread, "Thread open") != -1) + { + (void)pthread_setname_np(threadInfoSecond, "Open"); + } + + if(pthread_join(threadInfoFirst, NULL) != 0) // wait + printf("pthread_join - FAILED First\n"); + + if(pthread_join(threadInfoSecond, NULL) != 0) // wait + printf("pthread_join - FAILED Second\n"); + + + printf("End of lock test\n"); + sem_unlink("_tmp_semlockTimeoutTest_db-sem"); +} @@ -3326,21 +3406,29 @@ int main(int argc, char* argv[]) Suite* s = persistenceCommonLib_suite(); SRunner* sr = srunner_create(s); - srunner_set_xml(sr, "/tmp/persistenceCommonObjectTest.xml"); - srunner_set_log(sr, "/tmp/persistenceCommonObjectTest.log"); - srunner_run_all(sr, /*CK_NORMAL*/CK_VERBOSE); - nr_failed = srunner_ntests_failed(sr); - nr_run = srunner_ntests_run(sr); + if(argc == 1) + { + srunner_set_xml(sr, "/tmp/persistenceCommonObjectTest.xml"); + srunner_set_log(sr, "/tmp/persistenceCommonObjectTest.log"); + srunner_run_all(sr, /*CK_NORMAL*/CK_VERBOSE); + + nr_failed = srunner_ntests_failed(sr); + nr_run = srunner_ntests_run(sr); - tResult = srunner_results(sr); - for (i = 0; i < nr_run; i++) + tResult = srunner_results(sr); + for (i = 0; i < nr_run; i++) + { + (void) tr_rtype(tResult[i]); // get status of each test + } + + srunner_free(sr); + } + else { - (void) tr_rtype(tResult[i]); // get status of each test + doSemLockTimeoutTest(); } - srunner_free(sr); - dlt_free(); return (0 == nr_failed) ? EXIT_SUCCESS : EXIT_FAILURE; } -- cgit v1.2.1