libcamera: IPAManager: make IPAManager lifetime explicitly managed

If any ipa_context instances are destroyed after the IPAManager is
destroyed, then a segfault will occur, since the modules have been
unloaded by the IPAManager and the context function pointers have been
freed.

Fix this by making the lifetime of the IPAManager explicit, and make the
CameraManager construct and deconstruct (automatically, via a unique
pointer) the IPAManager.

Also update the IPA interface test to do the construction and
deconstruction of the IPAManager, as it does not use the CameraManager.

Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
This commit is contained in:
Paul Elder 2020-06-02 11:15:37 +09:00
parent 79d6662471
commit 46d544345c
4 changed files with 32 additions and 7 deletions

View file

@ -22,6 +22,9 @@ namespace libcamera {
class IPAManager class IPAManager
{ {
public: public:
IPAManager();
~IPAManager();
static IPAManager *instance(); static IPAManager *instance();
std::unique_ptr<IPAProxy> createIPA(PipelineHandler *pipe, std::unique_ptr<IPAProxy> createIPA(PipelineHandler *pipe,
@ -29,8 +32,7 @@ public:
uint32_t minVersion); uint32_t minVersion);
private: private:
IPAManager(); static IPAManager *self_;
~IPAManager();
void parseDir(const char *libDir, unsigned int maxDepth, void parseDir(const char *libDir, unsigned int maxDepth,
std::vector<std::string> &files); std::vector<std::string> &files);

View file

@ -15,6 +15,7 @@
#include "libcamera/internal/device_enumerator.h" #include "libcamera/internal/device_enumerator.h"
#include "libcamera/internal/event_dispatcher_poll.h" #include "libcamera/internal/event_dispatcher_poll.h"
#include "libcamera/internal/ipa_manager.h"
#include "libcamera/internal/log.h" #include "libcamera/internal/log.h"
#include "libcamera/internal/pipeline_handler.h" #include "libcamera/internal/pipeline_handler.h"
#include "libcamera/internal/thread.h" #include "libcamera/internal/thread.h"
@ -63,6 +64,8 @@ private:
std::vector<std::shared_ptr<PipelineHandler>> pipes_; std::vector<std::shared_ptr<PipelineHandler>> pipes_;
std::unique_ptr<DeviceEnumerator> enumerator_; std::unique_ptr<DeviceEnumerator> enumerator_;
IPAManager ipaManager_;
}; };
CameraManager::Private::Private(CameraManager *cm) CameraManager::Private::Private(CameraManager *cm)

View file

@ -93,8 +93,21 @@ LOG_DEFINE_CATEGORY(IPAManager)
* plain C API, or to transmit the data to the isolated process through IPC. * plain C API, or to transmit the data to the isolated process through IPC.
*/ */
IPAManager *IPAManager::self_ = nullptr;
/**
* \brief Construct an IPAManager instance
*
* The IPAManager class is meant to only be instantiated once, by the
* CameraManager. Pipeline handlers shall use the instance() function to access
* the IPAManager instance.
*/
IPAManager::IPAManager() IPAManager::IPAManager()
{ {
if (self_)
LOG(IPAManager, Fatal)
<< "Multiple IPAManager objects are not allowed";
unsigned int ipaCount = 0; unsigned int ipaCount = 0;
/* User-specified paths take precedence. */ /* User-specified paths take precedence. */
@ -134,27 +147,29 @@ IPAManager::IPAManager()
if (!ipaCount) if (!ipaCount)
LOG(IPAManager, Warning) LOG(IPAManager, Warning)
<< "No IPA found in '" IPA_MODULE_DIR "'"; << "No IPA found in '" IPA_MODULE_DIR "'";
self_ = this;
} }
IPAManager::~IPAManager() IPAManager::~IPAManager()
{ {
for (IPAModule *module : modules_) for (IPAModule *module : modules_)
delete module; delete module;
self_ = nullptr;
} }
/** /**
* \brief Retrieve the IPA manager instance * \brief Retrieve the IPA manager instance
* *
* The IPAManager is a singleton and can't be constructed manually. This * The IPAManager is constructed by the CameraManager. This function shall be
* function shall instead be used to retrieve the single global instance of the * used to retrieve the single instance of the manager.
* manager.
* *
* \return The IPA manager instance * \return The IPA manager instance
*/ */
IPAManager *IPAManager::instance() IPAManager *IPAManager::instance()
{ {
static IPAManager ipaManager; return self_;
return &ipaManager;
} }
/** /**

View file

@ -39,11 +39,15 @@ public:
~IPAInterfaceTest() ~IPAInterfaceTest()
{ {
delete notifier_; delete notifier_;
ipa_.reset();
ipaManager_.reset();
} }
protected: protected:
int init() override int init() override
{ {
ipaManager_ = make_unique<IPAManager>();
/* Create a pipeline handler for vimc. */ /* Create a pipeline handler for vimc. */
std::vector<PipelineHandlerFactory *> &factories = std::vector<PipelineHandlerFactory *> &factories =
PipelineHandlerFactory::factories(); PipelineHandlerFactory::factories();
@ -161,6 +165,7 @@ private:
std::shared_ptr<PipelineHandler> pipe_; std::shared_ptr<PipelineHandler> pipe_;
std::unique_ptr<IPAProxy> ipa_; std::unique_ptr<IPAProxy> ipa_;
std::unique_ptr<IPAManager> ipaManager_;
enum IPAOperationCode trace_; enum IPAOperationCode trace_;
EventNotifier *notifier_; EventNotifier *notifier_;
int fd_; int fd_;