From 0d98680bb5ef41e36a5a3399b1bbe740f3110030 Mon Sep 17 00:00:00 2001 From: Rafal Krypa Date: Wed, 11 Jan 2017 09:38:52 +0100 Subject: [PATCH] Wake up Cynara async thread from statusCallback Until now the thread handling communication with Cynara was woken up when new check was prepared for sending because cynara_async_create_request was expected to trigger statusCallback. When new data is prepared for sending to Cynara service, statusCallback requests that the cynara descriptor must be polled for writing and when it's ready, cynara_async_process will send the data to socket. But since Cynara release 0.12.0, cynara_async_check_cache may also trigger a statusCallback. This is because of underlying monotir entries and their periodic flush to Cynara service. This behavior of Cynara is not documented. To make sure that security-manager will restart polling of Cynara socket each time after statusCallback is triggered, the callBack itself will now take care of waking up the thread responsible for communication with Cynara. Change-Id: I8f9bf323166fccd97612dd85ec35c9befe5d00f9 Signed-off-by: Rafal Krypa --- src/common/cynara.cpp | 24 ++++++++++++++---------- src/common/include/cynara.h | 3 +++ 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/common/cynara.cpp b/src/common/cynara.cpp index 3be57a7..3755002 100644 --- a/src/common/cynara.cpp +++ b/src/common/cynara.cpp @@ -698,7 +698,7 @@ Cynara::Cynara() checkCynaraError(cynara_async_configuration_set_cache_size(p_conf, CACHE_SIZE), "Cannot set cynara async configuration cache size"); checkCynaraError( - cynara_async_initialize(&cynara, p_conf, &Cynara::statusCallback, &(pollFds[1])), + cynara_async_initialize(&cynara, p_conf, &Cynara::statusCallback, this), "Cannot connect to Cynara policy interface."); thread = std::thread(&Cynara::run, this); @@ -731,29 +731,34 @@ void Cynara::threadNotifyGet() LogError("Unexpected error while reading from eventfd: " << GetErrnoString(errno)); } -void Cynara::statusCallback(int oldFd, int newFd, cynara_async_status status, - void *ptr) +void Cynara::statusCallback(int oldFd, int newFd, cynara_async_status status) { - auto cynaraFd = static_cast(ptr); - LogDebug("Cynara status callback. " << "Status = " << status << ", oldFd = " << oldFd << ", newFd = " << newFd); if (newFd == -1) { - cynaraFd->events = 0; + pollFds[1].events = 0; } else { - cynaraFd->fd = newFd; + pollFds[1].fd = newFd; switch (status) { case CYNARA_STATUS_FOR_READ: - cynaraFd->events = POLLIN; + pollFds[1].events = POLLIN; break; case CYNARA_STATUS_FOR_RW: - cynaraFd->events = POLLIN | POLLOUT; + pollFds[1].events = POLLIN | POLLOUT; break; } } + + threadNotifyPut(); +} + +void Cynara::statusCallback(int oldFd, int newFd, cynara_async_status status, + void *ptr) +{ + static_cast(ptr)->statusCallback(oldFd, newFd, status); } void Cynara::responseCallback(cynara_check_id checkId, @@ -855,7 +860,6 @@ bool Cynara::check(const std::string &label, const std::string &privilege, &check_id, &Cynara::responseCallback, &promise), "Cannot check permission with Cynara."); - threadNotifyPut(); LogDebug("Waiting for response to Cynara query id " << check_id); } diff --git a/src/common/include/cynara.h b/src/common/include/cynara.h index 08e8ec6..c1da516 100644 --- a/src/common/include/cynara.h +++ b/src/common/include/cynara.h @@ -336,6 +336,9 @@ public: private: static const int CACHE_SIZE = 100; + + void statusCallback(int oldFd, int newFd, cynara_async_status status); + static void statusCallback(int oldFd, int newFd, cynara_async_status status, void *ptr); -- 2.7.4