SenseApiLib:Add isBeingDestroyed atomic flag for getter bailout
Since we have no choice but to access the sh_ptr<SenseApiLib> for a lib before we can get its Qutex, we use this flag to ensure that we can know whether the SenseApiLib data structure and its Qutex are still valid when we enter -- i.e, we ensure that the SenseApiLib object wasn't destroyed under our feet.
This commit is contained in:
@@ -324,10 +324,11 @@ public:
|
|||||||
const std::shared_ptr<DeviceAttachmentSpec>& spec,
|
const std::shared_ptr<DeviceAttachmentSpec>& spec,
|
||||||
const std::shared_ptr<ComponentThread> &caller,
|
const std::shared_ptr<ComponentThread> &caller,
|
||||||
Callback<attachSenseDeviceReqCbFn> cb,
|
Callback<attachSenseDeviceReqCbFn> cb,
|
||||||
|
std::shared_ptr<sense_api::SenseApiLib> &senseApiLib,
|
||||||
std::vector<std::reference_wrapper<Qutex>> requiredLocks)
|
std::vector<std::reference_wrapper<Qutex>> requiredLocks)
|
||||||
: SerializedAsynchronousContinuation<attachSenseDeviceReqCbFn>(
|
: SerializedAsynchronousContinuation<attachSenseDeviceReqCbFn>(
|
||||||
caller, cb, requiredLocks),
|
caller, cb, requiredLocks),
|
||||||
spec(spec)
|
spec(spec), senseApiLib(senseApiLib)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -344,26 +345,18 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** FIXME:
|
if (senseApiLib->isBeingDestroyed.load())
|
||||||
* We should acquire a spinlock here to ensure that the device isn't
|
|
||||||
* added in the interim while the async op executes.
|
|
||||||
*/
|
|
||||||
auto libOpt = sense_api::SenseApiManager::getInstance()
|
|
||||||
.getSenseApiLibByApiName(spec->api);
|
|
||||||
|
|
||||||
if (!libOpt)
|
|
||||||
{
|
{
|
||||||
std::cerr << std::string(__func__) + ": No library found for API '"
|
std::cerr << std::string(__func__) + ": Library is being destroyed"
|
||||||
<< spec->api << "'" << std::endl;
|
<< " for API '" << spec->api << "'. Bailing out." << std::endl;
|
||||||
callOriginalCb(false, spec);
|
callOriginalCb(false, spec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& lib = *libOpt.value();
|
if (!senseApiLib->senseApiDesc.sal_mgmt_libOps.attachDeviceReq)
|
||||||
if (!lib.senseApiDesc.sal_mgmt_libOps.attachDeviceReq)
|
|
||||||
{
|
{
|
||||||
std::cerr << std::string(__func__) + ": attachDeviceReq() is NULL "
|
std::cerr << std::string(__func__) + ": attachDeviceReq() is NULL "
|
||||||
"for library '" << lib.libraryPath << "'" << std::endl;
|
"for library '" << senseApiLib->libraryPath << "'" << std::endl;
|
||||||
callOriginalCb(false, spec);
|
callOriginalCb(false, spec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -391,7 +384,7 @@ public:
|
|||||||
<< spec->deviceIdentifier << " to body thread" << "\n";
|
<< spec->deviceIdentifier << " to body thread" << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
lib.senseApiDesc.sal_mgmt_libOps.attachDeviceReq(
|
senseApiLib->senseApiDesc.sal_mgmt_libOps.attachDeviceReq(
|
||||||
spec, threadForAttachment,
|
spec, threadForAttachment,
|
||||||
{context, std::bind(
|
{context, std::bind(
|
||||||
&AttachSenseDeviceReq::attachSenseDeviceReq2,
|
&AttachSenseDeviceReq::attachSenseDeviceReq2,
|
||||||
@@ -421,32 +414,25 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** FIXME:
|
if (senseApiLib->isBeingDestroyed.load())
|
||||||
* We should acquire a spinlock here to ensure that the device isn't
|
|
||||||
* removed in the interim while the async op executes.
|
|
||||||
*/
|
|
||||||
auto libOpt = sense_api::SenseApiManager::getInstance()
|
|
||||||
.getSenseApiLibByApiName(spec->api);
|
|
||||||
|
|
||||||
if (!libOpt)
|
|
||||||
{
|
{
|
||||||
std::cerr << std::string(__func__) + ": No library found for API '"
|
std::cerr << std::string(__func__) + ": Library is being destroyed"
|
||||||
<< spec->api << "'" << std::endl;
|
<< " for API '" << spec->api << "'. Bailing out." << std::endl;
|
||||||
callOriginalCb(false, spec);
|
callOriginalCb(false, spec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto& lib = *libOpt.value();
|
|
||||||
if (!lib.senseApiDesc.sal_mgmt_libOps.detachDeviceReq)
|
if (!senseApiLib->senseApiDesc.sal_mgmt_libOps.detachDeviceReq)
|
||||||
{
|
{
|
||||||
std::cerr << std::string(__func__) + ": detachDeviceReq() is NULL "
|
std::cerr << std::string(__func__) + ": detachDeviceReq() is NULL "
|
||||||
"for library '" << lib.libraryPath << "'" << std::endl;
|
"for library '" << senseApiLib->libraryPath << "'" << std::endl;
|
||||||
callOriginalCb(false, spec);
|
callOriginalCb(false, spec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sense_api::SenseApiManager::getInstance().qutex.release();
|
sense_api::SenseApiManager::getInstance().qutex.release();
|
||||||
|
|
||||||
lib.senseApiDesc.sal_mgmt_libOps.detachDeviceReq(
|
senseApiLib->senseApiDesc.sal_mgmt_libOps.detachDeviceReq(
|
||||||
spec,
|
spec,
|
||||||
{context, std::bind(
|
{context, std::bind(
|
||||||
&DetachSenseDeviceReq::detachSenseDeviceReq2,
|
&DetachSenseDeviceReq::detachSenseDeviceReq2,
|
||||||
@@ -465,6 +451,7 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
std::shared_ptr<DeviceAttachmentSpec> spec;
|
std::shared_ptr<DeviceAttachmentSpec> spec;
|
||||||
|
std::shared_ptr<sense_api::SenseApiLib> senseApiLib;
|
||||||
};
|
};
|
||||||
|
|
||||||
void DeviceManager::attachSenseDeviceReq(
|
void DeviceManager::attachSenseDeviceReq(
|
||||||
@@ -489,7 +476,7 @@ void DeviceManager::attachSenseDeviceReq(
|
|||||||
auto& lib = *libOpt.value();
|
auto& lib = *libOpt.value();
|
||||||
|
|
||||||
auto request = std::make_shared<AttachSenseDeviceReq>(
|
auto request = std::make_shared<AttachSenseDeviceReq>(
|
||||||
spec, caller, cb,
|
spec, caller, cb, libOpt.value(),
|
||||||
LockSet<attachSenseDeviceReqCbFn>::Set{
|
LockSet<attachSenseDeviceReqCbFn>::Set{
|
||||||
std::ref(sense_api::SenseApiManager::getInstance().qutex),
|
std::ref(sense_api::SenseApiManager::getInstance().qutex),
|
||||||
std::ref(lib.qutex)
|
std::ref(lib.qutex)
|
||||||
@@ -524,7 +511,7 @@ void DeviceManager::detachSenseDeviceReq(
|
|||||||
auto& lib = *libOpt.value();
|
auto& lib = *libOpt.value();
|
||||||
|
|
||||||
auto request = std::make_shared<DetachSenseDeviceReq>(
|
auto request = std::make_shared<DetachSenseDeviceReq>(
|
||||||
spec, caller, cb,
|
spec, caller, cb, libOpt.value(),
|
||||||
LockSet<detachSenseDeviceReqCbFn>::Set{
|
LockSet<detachSenseDeviceReqCbFn>::Set{
|
||||||
std::ref(sense_api::SenseApiManager::getInstance().qutex),
|
std::ref(sense_api::SenseApiManager::getInstance().qutex),
|
||||||
std::ref(lib.qutex)
|
std::ref(lib.qutex)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <atomic>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@@ -30,7 +31,7 @@ public:
|
|||||||
SenseApiLib(
|
SenseApiLib(
|
||||||
const std::string& path, void *_dlopen_handle,
|
const std::string& path, void *_dlopen_handle,
|
||||||
SMO_GET_SENSE_API_DESC_FN_TYPEDEF *descFn)
|
SMO_GET_SENSE_API_DESC_FN_TYPEDEF *descFn)
|
||||||
: libraryPath(path), qutex("SenseApiLib-" + path),
|
: libraryPath(path), qutex("SenseApiLib-" + path), isBeingDestroyed(false),
|
||||||
dlopen_handle(_dlopen_handle, DlCloser()),
|
dlopen_handle(_dlopen_handle, DlCloser()),
|
||||||
SMO_GET_SENSE_API_DESC_FN_NAME(descFn)
|
SMO_GET_SENSE_API_DESC_FN_NAME(descFn)
|
||||||
{}
|
{}
|
||||||
@@ -50,6 +51,7 @@ public:
|
|||||||
public:
|
public:
|
||||||
std::string libraryPath;
|
std::string libraryPath;
|
||||||
Qutex qutex;
|
Qutex qutex;
|
||||||
|
std::atomic<bool> isBeingDestroyed;
|
||||||
std::unique_ptr<void, DlCloser> dlopen_handle;
|
std::unique_ptr<void, DlCloser> dlopen_handle;
|
||||||
/* UNIMPLEMENTED: API-specific cmdline options. These affect this specific
|
/* UNIMPLEMENTED: API-specific cmdline options. These affect this specific
|
||||||
* sense api lib's behaviour globally.
|
* sense api lib's behaviour globally.
|
||||||
|
|||||||
@@ -228,6 +228,10 @@ std::string SenseApiManager::stringifyLibs() const
|
|||||||
|
|
||||||
void SenseApiManager::initializeSenseApiLib(SenseApiLib& lib)
|
void SenseApiManager::initializeSenseApiLib(SenseApiLib& lib)
|
||||||
{
|
{
|
||||||
|
/** FIXME:
|
||||||
|
* When we eventually make this method async, this method should acquire
|
||||||
|
* the SenseApiManager's main CRUD qutex.
|
||||||
|
*/
|
||||||
if (!lib.senseApiDesc.sal_mgmt_libOps.initializeInd)
|
if (!lib.senseApiDesc.sal_mgmt_libOps.initializeInd)
|
||||||
{
|
{
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
@@ -239,6 +243,11 @@ void SenseApiManager::initializeSenseApiLib(SenseApiLib& lib)
|
|||||||
|
|
||||||
void SenseApiManager::finalizeSenseApiLib(SenseApiLib& lib)
|
void SenseApiManager::finalizeSenseApiLib(SenseApiLib& lib)
|
||||||
{
|
{
|
||||||
|
/** FIXME:
|
||||||
|
* When we eventually make this method async, this flag should only be set
|
||||||
|
* after acquiring the SenseApiManager's main CRUD qutex.
|
||||||
|
*/
|
||||||
|
lib.isBeingDestroyed.store(true);
|
||||||
if (!lib.senseApiDesc.sal_mgmt_libOps.finalizeInd)
|
if (!lib.senseApiDesc.sal_mgmt_libOps.finalizeInd)
|
||||||
{
|
{
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
|
|||||||
Reference in New Issue
Block a user