diff options
author | Ingo Huerner <ingo_huerner@mentor.com> | 2017-02-21 10:21:29 +0100 |
---|---|---|
committer | Ingo Huerner <ingo_huerner@mentor.com> | 2017-02-21 10:21:29 +0100 |
commit | e88cdcdee8aa92d62b6a77ed1e938afb107229f4 (patch) | |
tree | 61527f6575824231743618e440f9632476f77cc6 | |
parent | 2e190294dfd19ab9612e2576ebbaeff738990f70 (diff) | |
download | persistence-client-library-e88cdcdee8aa92d62b6a77ed1e938afb107229f4.tar.gz |
Handling of dbus pending calls rework (mutex handling improved, added condvar).
Improved registration to PAS: if PAS is not available when calling pclInit, PCL registers itself as soon as PAS will be available
-rw-r--r-- | src/persistence_client_library.c | 112 | ||||
-rw-r--r-- | src/persistence_client_library_data_organization.c | 3 | ||||
-rw-r--r-- | src/persistence_client_library_data_organization.h | 4 | ||||
-rw-r--r-- | src/persistence_client_library_dbus_cmd.c | 14 | ||||
-rw-r--r-- | src/persistence_client_library_dbus_service.c | 150 | ||||
-rw-r--r-- | src/persistence_client_library_dbus_service.h | 3 | ||||
-rw-r--r-- | src/persistence_client_library_pas_interface.c | 26 |
7 files changed, 227 insertions, 85 deletions
diff --git a/src/persistence_client_library.c b/src/persistence_client_library.c index 1739e5c..1b1b551 100644 --- a/src/persistence_client_library.c +++ b/src/persistence_client_library.c @@ -238,82 +238,69 @@ static int private_pclInitLibrary(const char* appName, int shutdownMode) { int rval = 1; char blacklistPath[PERS_ORG_MAX_LENGTH_PATH_FILENAME] = {0}; - int lock = pthread_mutex_lock(&gDbusPendingRegMtx); // block until pending received - if(lock == 0) - { - gShutdownMode = shutdownMode; + + gShutdownMode = shutdownMode; #if USE_APPCHECK - doInitAppcheck(appName); // check if we have a trusted application + doInitAppcheck(appName); // check if we have a trusted application #endif #if USE_FILECACHE - DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("Using the filecache!!!")); - pfcInitCache(appName); + DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("Using the filecache!!!")); + pfcInitCache(appName); #endif - // Assemble backup blacklist path - snprintf(blacklistPath, PERS_ORG_MAX_LENGTH_PATH_FILENAME, "%s%s/%s", CACHEPREFIX, appName, gBackupFilename); + // Assemble backup blacklist path + snprintf(blacklistPath, PERS_ORG_MAX_LENGTH_PATH_FILENAME, "%s%s/%s", CACHEPREFIX, appName, gBackupFilename); - if(readBlacklistConfigFile(blacklistPath) == -1) - { - DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("initLibrary - Err access blacklist:"), DLT_STRING(blacklistPath)); - } + if(readBlacklistConfigFile(blacklistPath) == -1) + { + DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("initLibrary - Err access blacklist:"), DLT_STRING(blacklistPath)); + } - if(setup_dbus_mainloop() == -1) - { - DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("initLibrary - Failed to setup main loop")); - pthread_mutex_unlock(&gDbusPendingRegMtx); - return EPERS_DBUS_MAINLOOP; - } + if(setup_dbus_mainloop() == -1) + { + DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("initLibrary - Failed to setup main loop")); + return EPERS_DBUS_MAINLOOP; + } - if(gShutdownMode != PCL_SHUTDOWN_TYPE_NONE) - { - if(register_lifecycle(shutdownMode) == -1) // register for lifecycle dbus messages - { - DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("initLibrary => Failed reg to LC dbus interface")); - pthread_mutex_unlock(&gDbusPendingRegMtx); - return EPERS_REGISTER_LIFECYCLE; - } - } + + if(gShutdownMode != PCL_SHUTDOWN_TYPE_NONE) + { + if(register_lifecycle(shutdownMode) == -1) // register for lifecycle dbus messages + { + DLT_LOG(gPclDLTContext, DLT_LOG_WARN, DLT_STRING("initLibrary => Failed reg to LC dbus interface")); + } + } #if USE_PASINTERFACE - DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("PAS interface is enabled!!")); - if(register_pers_admin_service() == -1) - { - DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("initLibrary - Failed reg to PAS dbus interface")); - pthread_mutex_unlock(&gDbusPendingRegMtx); - return EPERS_REGISTER_ADMIN; - } - else - { - DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("initLibrary - Successfully established IPC protocol for PCL.")); - } + DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("PAS interface is enabled!!")); + if(register_pers_admin_service() == -1) + { + DLT_LOG(gPclDLTContext, DLT_LOG_WARN, DLT_STRING("initLibrary - Failed reg to PAS dbus interface")); + } + else + { + DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("initLibrary - Successfully established IPC protocol for PCL.")); + gPasRegistered = 1; // remember registration to PAS + } #else - DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("PAS interface not enabled, enable with \"./configure --enable-pasinterface\"")); + DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("PAS interface not enabled, enable with \"./configure --enable-pasinterface\"")); #endif - if((rval = load_custom_plugins(customAsyncInitClbk)) < 0) // load custom plugins - { - DLT_LOG(gPclDLTContext, DLT_LOG_WARN, DLT_STRING("Failed to load custom plugins")); - pthread_mutex_unlock(&gDbusPendingRegMtx); - return rval; - } - - init_key_handle_array(); + if((rval = load_custom_plugins(customAsyncInitClbk)) < 0) // load custom plugins + { + DLT_LOG(gPclDLTContext, DLT_LOG_WARN, DLT_STRING("Failed to load custom plugins")); + return rval; + } - pers_unlock_access(); + init_key_handle_array(); - strncpy(gAppId, appName, PERS_RCT_MAX_LENGTH_RESPONSIBLE); // assign application name - gAppId[PERS_RCT_MAX_LENGTH_RESPONSIBLE-1] = '\0'; + strncpy(gAppId, appName, PERS_RCT_MAX_LENGTH_RESPONSIBLE); // assign application name + gAppId[PERS_RCT_MAX_LENGTH_RESPONSIBLE-1] = '\0'; - pthread_mutex_unlock(&gDbusPendingRegMtx); - } - else - { - DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("private_pclInitLibrary - mutex lock failed:"), DLT_INT(lock)); - } + pers_unlock_access(); return rval; } @@ -371,12 +358,13 @@ static int private_pclDeinitLibrary(void) #if USE_PASINTERFACE == 1 rval = unregister_pers_admin_service(); if(0 != rval) - { - DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pclDeinitLibrary - Err to de-initialize IPC protocol for PCL.")); - } + { + DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pclDeinitLibrary - Err to de-initialize IPC protocol for PCL.")); + } else { - DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("pclDeinitLibrary - Succ de-initialized IPC protocol for PCL.")); + DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("pclDeinitLibrary - Succ de-initialized IPC protocol for PCL.")); + gPasRegistered = 0; } #endif @@ -400,8 +388,6 @@ static int private_pclDeinitLibrary(void) deleteBackupTree(); deleteNotifyTree(); - pthread_mutex_unlock(&gDbusPendingRegMtx); - #if USE_FILECACHE pfcDeinitCache(); #endif diff --git a/src/persistence_client_library_data_organization.c b/src/persistence_client_library_data_organization.c index ef77d2f..db26ef5 100644 --- a/src/persistence_client_library_data_organization.c +++ b/src/persistence_client_library_data_organization.c @@ -27,6 +27,9 @@ char gAppId[PERS_RCT_MAX_LENGTH_RESPONSIBLE] = { [0 ... PERS_RCT_MAX_LENGTH_RESP /// flag to indicate if client library has been initialized unsigned int gPclInitCounter = 0; +/// flag to indicate if PCL has registered to PAS +int gPasRegistered = 0; + int(* gChangeNotifyCallback)(pclNotification_s * notifyStruct); /// character lookup table used for parsing configuration files diff --git a/src/persistence_client_library_data_organization.h b/src/persistence_client_library_data_organization.h index 211fb3a..429b77a 100644 --- a/src/persistence_client_library_data_organization.h +++ b/src/persistence_client_library_data_organization.h @@ -280,6 +280,10 @@ extern unsigned int gPclInitCounter __attribute__ ((visibility ("hidden"))); extern int gDbusPendingRvalue __attribute__ ((visibility ("hidden"))); +/// flag to indicate if PCL has registered to PAS +extern int gPasRegistered; + + /** * @brief definition of change callback function * diff --git a/src/persistence_client_library_dbus_cmd.c b/src/persistence_client_library_dbus_cmd.c index 0f17bd4..18b5f74 100644 --- a/src/persistence_client_library_dbus_cmd.c +++ b/src/persistence_client_library_dbus_cmd.c @@ -457,11 +457,15 @@ void msg_pending_func(DBusPendingCall *call, void *data) DBusError err; dbus_error_init(&err); + DBusMessage *message = NULL; + (void)data; - DBusMessage *message = dbus_pending_call_steal_reply(call); + pthread_mutex_lock(&gDbusPendingRegMtx); + + message = dbus_pending_call_steal_reply(call); - if (dbus_set_error_from_message(&err, message)) + if(dbus_set_error_from_message(&err, message)) { DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("msgPendFunc - Access denied") ); } @@ -472,8 +476,12 @@ void msg_pending_func(DBusPendingCall *call, void *data) } gDbusPendingRvalue = replyArg; // set the return value - dbus_message_unref(message); + + gDbusPendingCondValue = 1; + pthread_cond_signal(&gDbusPendingCond); // unlock the mutex because we have received the reply to the dbus message pthread_mutex_unlock(&gDbusPendingRegMtx); + + dbus_message_unref(message); } diff --git a/src/persistence_client_library_dbus_service.c b/src/persistence_client_library_dbus_service.c index b19d607..981982e 100644 --- a/src/persistence_client_library_dbus_service.c +++ b/src/persistence_client_library_dbus_service.c @@ -29,15 +29,16 @@ DLT_IMPORT_CONTEXT(gPclDLTContext); pthread_mutex_t gDbusPendingRegMtx = PTHREAD_MUTEX_INITIALIZER; - -pthread_mutex_t gDeliverpMtx = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t gDbusPendingCond = PTHREAD_COND_INITIALIZER; +int gDbusPendingCondValue = 0; pthread_mutex_t gMainCondMtx = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t gMainLoopCond = PTHREAD_COND_INITIALIZER; +int gMainLoopCondValue = 0; -pthread_t gMainLoopThread; +pthread_mutex_t gDeliverpMtx = PTHREAD_MUTEX_INITIALIZER; -int gMainLoopCondValue = 0; +pthread_t gMainLoopThread; const char* gDbusLcConsDest = "org.genivi.NodeStateManager"; @@ -47,6 +48,7 @@ const char* gDbusLcInterface = "org.genivi.NodeStateManager.Consumer"; const char* gDbusLcCons = "/org/genivi/NodeStateManager/Consumer"; const char* gDbusLcConsMsg = "LifecycleRequest"; + const char* gDbusPersAdminConsInterface = "org.genivi.persistence.adminconsumer"; const char* gPersAdminConsumerPath = "/org/genivi/persistence/adminconsumer"; const char* gDbusPersAdminPath = "/org/genivi/persistence/admin"; @@ -103,10 +105,54 @@ static void unregisterMessageHandler(DBusConnection *connection, void *user_data } +#if USE_PASINTERFACE + +void* doSendPasRegister(void *data) +{ + long rval = 0; + + rval = (long)register_pers_admin_service(); // register to PAS + + return (void*)rval; +} + +void* registerToPas(void* data) +{ + pthread_t thread; + long* retval = NULL; + + // create send thread in order to wait until registration succeeded + pthread_create(&thread, NULL, doSendPasRegister, NULL); + + // wait untill registration has finished + pthread_join(thread, (void**)&retval); + + if((long)retval == -1) + { + //printf("==> PAS Appeared - register failed\n"); + DLT_LOG(gPclDLTContext, DLT_LOG_WARN, DLT_STRING("NameOwnerChanged - Failed reg to PAS dbus interface")); + } + else + { + //printf("==> PAS Appeared - register success\n"); + DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("NameOwnerChanged - Successfully established IPC protocol for PCL.")); + gPasRegistered = 1; // remember registration to PAS + } + + return NULL; +} + +#endif + + + /* catches messages not directed to any registered object path ("garbage collector") */ static DBusHandlerResult handleObjectPathMessageFallback(DBusConnection * connection, DBusMessage * message, void * user_data) { DBusHandlerResult result = DBUS_HANDLER_RESULT_HANDLED; + DBusError error; + DBusMessage *reply; + dbus_error_init (&error); (void)user_data; if((0==strcmp(gDbusPersAdminConsInterface, dbus_message_get_interface(message)))) @@ -134,9 +180,6 @@ static DBusHandlerResult handleObjectPathMessageFallback(DBusConnection * connec if(validMessage == 1) { - DBusError error; - DBusMessage *reply; - dbus_error_init (&error); char *ldbid, *user_no, *seat_no; if (!dbus_message_get_args(message, &error, DBUS_TYPE_STRING, ¬ifyStruct.resource_id, @@ -157,7 +200,7 @@ static DBusHandlerResult handleObjectPathMessageFallback(DBusConnection * connec DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("handleObjPathMsgFback - DBus No mem"), DLT_STRING(dbus_message_get_interface(message)) ); } - result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;; + result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; dbus_message_unref(reply); } else @@ -178,8 +221,88 @@ static DBusHandlerResult handleObjectPathMessageFallback(DBusConnection * connec } dbus_connection_flush(connection); } + else + { + result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + } + else + { + result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } } +#if USE_PASINTERFACE + else if((0==strcmp("org.freedesktop.DBus", dbus_message_get_interface(message)))) + { + if(dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL) + { + if((0==strcmp("NameOwnerChanged", dbus_message_get_member(message)))) + { + char* dbusname = NULL; + char* new_owner = NULL; + char* old_owner = NULL; + + if(!dbus_message_get_args(message, &error, DBUS_TYPE_STRING, &dbusname, + DBUS_TYPE_STRING, &new_owner, + DBUS_TYPE_STRING, &old_owner, + DBUS_TYPE_INVALID)) + { + reply = dbus_message_new_error(message, error.name, error.message); + + if(reply == 0) + { + DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("handleObjPathMsgFback - DBus No mem"), DLT_STRING(dbus_message_get_interface(message)) ); + } + + if(!dbus_connection_send(connection, reply, 0)) + { + DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("handleObjPathMsgFback - DBus No mem"), DLT_STRING(dbus_message_get_interface(message)) ); + } + + result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + dbus_message_unref(reply); + } + else + { + if(0==strcmp(gDbusPersAdminInterface, dbusname)) // listen when PAS becomes available/unavailable + { + if(new_owner != NULL) + { + if(new_owner[0] == '\0') + { + DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("NameOwnerChanged - PAS service appeared")); + if(gPasRegistered == 0) + { + pthread_t thread; + // create register thread to prevent blocking of mainloop until registration has finished + pthread_create(&thread, NULL, registerToPas, NULL); + } + } + } + + if(old_owner != NULL) + { + if(old_owner[0] == '\0') + { + printf("PAS Disappeared\n"); + DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("NameOwnerChanged - PAS service disappeared")); + gPasRegistered = 0; // just remember not PAS disappeared, no ned to unregister as service is not available anymore + } + } + } + } + } + else + { + result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + } + } +#endif + else + { + result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } return result; } @@ -412,11 +535,11 @@ int setup_dbus_mainloop(void) else { // persistence administrator message - const struct DBusObjectPathVTable vtablePersAdmin = {unregisterMessageHandler, checkPersAdminMsg, NULL, NULL, NULL, NULL}; + static const struct DBusObjectPathVTable vtablePersAdmin = {unregisterMessageHandler, checkPersAdminMsg, NULL, NULL, NULL, NULL}; // lifecycle message - const struct DBusObjectPathVTable vtableLifecycle = {unregisterMessageHandler, checkLifecycleMsg, NULL, NULL, NULL, NULL}; + static const struct DBusObjectPathVTable vtableLifecycle = {unregisterMessageHandler, checkLifecycleMsg, NULL, NULL, NULL, NULL}; // fallback - const struct DBusObjectPathVTable vtableFallback = {unregisterObjectPathFallback, handleObjectPathMessageFallback, NULL, NULL, NULL, NULL}; + static const struct DBusObjectPathVTable vtableFallback = {unregisterObjectPathFallback, handleObjectPathMessageFallback, NULL, NULL, NULL, NULL}; #if USE_PASINTERFACE != 1 (void)vtablePersAdmin; @@ -428,6 +551,9 @@ int setup_dbus_mainloop(void) gPollInfo.fds[0].events = POLLIN; dbus_bus_add_match(conn, "type='signal',interface='org.genivi.persistence.admin',member='PersistenceModeChanged',path='/org/genivi/persistence/admin'", &err); +#if USE_PASINTERFACE + dbus_bus_add_match(conn, "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged',path='/org/freedesktop/DBus'", &err); +#endif // register for messages if ( (TRUE==dbus_connection_register_object_path(conn, gDbusLcConsPath, &vtableLifecycle, conn)) @@ -670,13 +796,11 @@ int deliverToMainloop(MainLoopData_u* payload) pthread_mutex_lock(&gDeliverpMtx); // make sure deliverToMainloop will be used exclusively rval = deliverToMainloop_NM(payload); - pthread_mutex_lock(&gMainCondMtx); // mutex needed for pthread condition used to wait on other thread (mainloop) while(0 == gMainLoopCondValue) pthread_cond_wait(&gMainLoopCond, &gMainCondMtx); pthread_mutex_unlock(&gMainCondMtx); - gMainLoopCondValue = 0; pthread_mutex_unlock(&gDeliverpMtx); diff --git a/src/persistence_client_library_dbus_service.h b/src/persistence_client_library_dbus_service.h index 365d11b..d3f70d6 100644 --- a/src/persistence_client_library_dbus_service.h +++ b/src/persistence_client_library_dbus_service.h @@ -65,6 +65,9 @@ typedef struct MainLoopData_u_{ /// dbus pending mutex => visibility "hidden" to prevent the use outside the library extern pthread_mutex_t gDbusPendingRegMtx __attribute__ ((visibility ("hidden"))); +extern pthread_cond_t gDbusPendingCond; +extern int gDbusPendingCondValue; + /// dbus mainloop conditional variable => visibility "hidden" to prevent the use outside the library extern pthread_mutex_t gMainCondMtx __attribute__ ((visibility ("hidden"))); /// dbus mainloop mutex => visibility "hidden" to prevent the use outside the library diff --git a/src/persistence_client_library_pas_interface.c b/src/persistence_client_library_pas_interface.c index 2e41bc7..cda4e01 100644 --- a/src/persistence_client_library_pas_interface.c +++ b/src/persistence_client_library_pas_interface.c @@ -191,13 +191,21 @@ int register_pers_admin_service(void) if(-1 == deliverToMainloop(&data)) { - DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("regPas - failed write pipe"), DLT_INT(errno)); - rval = -1; + DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("regPas - failed write pipe"), DLT_INT(errno)); + rval = -1; } else { - pthread_mutex_lock(&gDbusPendingRegMtx); // block until pending received + pthread_mutex_lock(&gDbusPendingRegMtx); + while(0 == gDbusPendingCondValue) + { + pthread_cond_wait(&gDbusPendingCond, &gDbusPendingRegMtx); + } + pthread_mutex_unlock(&gDbusPendingRegMtx); + + gDbusPendingCondValue = 0; rval = gDbusPendingRvalue; + } return rval; } @@ -218,13 +226,19 @@ int unregister_pers_admin_service(void) if(-1 == deliverToMainloop(&data)) { - DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("unregPas - failed write pipe"), DLT_INT(errno)); - rval = -1; + DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("unregPas - failed write pipe"), DLT_INT(errno)); + rval = -1; } else { - pthread_mutex_lock(&gDbusPendingRegMtx); // block until pending received + pthread_mutex_lock(&gDbusPendingRegMtx); + while(0 == gDbusPendingCondValue) + pthread_cond_wait(&gDbusPendingCond, &gDbusPendingRegMtx); + pthread_mutex_unlock(&gDbusPendingRegMtx); + + gDbusPendingCondValue = 0; rval = gDbusPendingRvalue; + } return rval; } |