summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIngo Huerner <ingo_huerner@mentor.com>2017-04-06 14:11:59 +0200
committerIngo Huerner <ingo_huerner@mentor.com>2017-04-06 14:11:59 +0200
commitc1cd0d398ee0c25b5af6e4ff96b9991a1b24959d (patch)
tree872d1975227069aa0723d75c6574a6a063738f79
parentbfbb7bdf51ded03c2277992df3fb619488bd26a8 (diff)
downloadpersistence-common-object-c1cd0d398ee0c25b5af6e4ff96b9991a1b24959d.tar.gz
Replaced sem_wait with sem_timedwait in pers_lldb_open and pers_lldb_close with 5 sec timeout
-rw-r--r--inc/protected/persComErrors.h1
-rw-r--r--src/key-value-store/pers_low_level_db_access.c17
-rw-r--r--test/test_pco_key_value_store.c108
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 <dlt/dlt_common.h>
#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 <check.h>
@@ -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;
}