From 4d295519b64305ed8cf639fe0a48bdfc301c21e7 Mon Sep 17 00:00:00 2001 From: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com> Date: Mon, 22 Feb 2016 10:24:52 -0500 Subject: [PATCH] videomanager: fix bad memory access - remove videoManager global instance. - allocate a VideoManager instance when Manager instance is created. - add Manager::getVideoManager() method to get this instance. - force getSignalHandlers() to be called before Manager instance creation. All of this prevents VideoManager to access to signal handlers map, already destroyed, causing a memory access violation. Change-Id: I21ebff08fa8d49e797f99299de12dab023c37769 Tuleap: #413 --- src/client/videomanager.cpp | 45 +++++++++++++-------------- src/client/videomanager.h | 2 -- src/manager.cpp | 3 ++ src/manager.h | 8 +++-- src/media/video/video_rtp_session.cpp | 2 +- src/ring_api.cpp | 6 ++++ src/sip/sipcall.cpp | 4 +-- 7 files changed, 39 insertions(+), 31 deletions(-) diff --git a/src/client/videomanager.cpp b/src/client/videomanager.cpp index 10f4b9b48e..16a8a52ccc 100644 --- a/src/client/videomanager.cpp +++ b/src/client/videomanager.cpp @@ -39,8 +39,6 @@ namespace DRing { -using ring::videoManager; - void registerVideoHandlers(const std::map<std::string, std::shared_ptr<CallbackWrapperBase>>& handlers) @@ -61,65 +59,65 @@ registerVideoHandlers(const std::map<std::string, std::vector<std::string> getDeviceList() { - return videoManager.videoDeviceMonitor.getDeviceList(); + return ring::Manager::instance().getVideoManager().videoDeviceMonitor.getDeviceList(); } VideoCapabilities getCapabilities(const std::string& name) { - return videoManager.videoDeviceMonitor.getCapabilities(name); + return ring::Manager::instance().getVideoManager().videoDeviceMonitor.getCapabilities(name); } std::string getDefaultDevice() { - return videoManager.videoDeviceMonitor.getDefaultDevice(); + return ring::Manager::instance().getVideoManager().videoDeviceMonitor.getDefaultDevice(); } void setDefaultDevice(const std::string& name) { RING_DBG("Setting default device to %s", name.c_str()); - videoManager.videoDeviceMonitor.setDefaultDevice(name); + ring::Manager::instance().getVideoManager().videoDeviceMonitor.setDefaultDevice(name); } std::map<std::string, std::string> getSettings(const std::string& name) { - return videoManager.videoDeviceMonitor.getSettings(name).to_map(); + return ring::Manager::instance().getVideoManager().videoDeviceMonitor.getSettings(name).to_map(); } void applySettings(const std::string& name, const std::map<std::string, std::string>& settings) { - videoManager.videoDeviceMonitor.applySettings(name, settings); + ring::Manager::instance().getVideoManager().videoDeviceMonitor.applySettings(name, settings); } void startCamera() { - videoManager.videoPreview = ring::getVideoCamera(); - videoManager.started = switchToCamera(); + ring::Manager::instance().getVideoManager().videoPreview = ring::getVideoCamera(); + ring::Manager::instance().getVideoManager().started = switchToCamera(); } void stopCamera() { if (switchInput("")) - videoManager.started = false; - videoManager.videoPreview.reset(); + ring::Manager::instance().getVideoManager().started = false; + ring::Manager::instance().getVideoManager().videoPreview.reset(); } bool switchInput(const std::string& resource) { if (auto call = ring::Manager::instance().getCurrentCall()) { - // TODO remove this part when clients are updated to use CallManager::switchInput + // TODO remove this part when clients are updated to use Callring::Manager::switchInput call->switchInput(resource); return true; } else { - if (auto input = videoManager.videoInput.lock()) + if (auto input = ring::Manager::instance().getVideoManager().videoInput.lock()) return input->switchInput(resource).valid(); RING_WARN("Video input not initialized"); } @@ -129,13 +127,13 @@ switchInput(const std::string& resource) bool switchToCamera() { - return switchInput(videoManager.videoDeviceMonitor.getMRLForDefaultDevice()); + return switchInput(ring::Manager::instance().getVideoManager().videoDeviceMonitor.getMRLForDefaultDevice()); } bool hasCameraStarted() { - return videoManager.started; + return ring::Manager::instance().getVideoManager().started; } void @@ -151,13 +149,13 @@ registerSinkTarget(const std::string& sinkId, const SinkTarget& target) void addVideoDevice(const std::string &node) { - videoManager.videoDeviceMonitor.addDevice(node); + ring::Manager::instance().getVideoManager().videoDeviceMonitor.addDevice(node); } void removeVideoDevice(const std::string &node) { - videoManager.videoDeviceMonitor.removeDevice(node); + ring::Manager::instance().getVideoManager().videoDeviceMonitor.removeDevice(node); } void* @@ -181,24 +179,23 @@ releaseFrame(void* frame) namespace ring { -VideoManager videoManager; - std::shared_ptr<video::VideoFrameActiveWriter> getVideoCamera() { - if (auto input = videoManager.videoInput.lock()) + auto& vmgr = Manager::instance().getVideoManager(); + if (auto input = vmgr.videoInput.lock()) return input; - videoManager.started = false; + vmgr.started = false; auto input = std::make_shared<video::VideoInput>(); - videoManager.videoInput = input; + vmgr.videoInput = input; return input; } video::VideoDeviceMonitor& getVideoDeviceMonitor() { - return videoManager.videoDeviceMonitor; + return Manager::instance().getVideoManager().videoDeviceMonitor; } } // namespace ring diff --git a/src/client/videomanager.h b/src/client/videomanager.h index 47ff88dff5..b9c0078097 100644 --- a/src/client/videomanager.h +++ b/src/client/videomanager.h @@ -51,8 +51,6 @@ struct VideoManager std::atomic_bool started; }; -extern VideoManager videoManager; - std::shared_ptr<video::VideoFrameActiveWriter> getVideoCamera(); video::VideoDeviceMonitor& getVideoDeviceMonitor(); diff --git a/src/manager.cpp b/src/manager.cpp index 4a78c54824..eccb225949 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -213,6 +213,9 @@ Manager::Manager() : , ringbufferpool_(new RingBufferPool) , callFactory(), conferenceMap_() , accountFactory_(), ice_tf_() +#ifdef RING_VIDEO + , videoManager_(new VideoManager) +#endif { // initialize random generator // mt19937_64 should be seeded with 2 x 32 bits diff --git a/src/manager.h b/src/manager.h index 688c9a087c..735d38de00 100644 --- a/src/manager.h +++ b/src/manager.h @@ -66,6 +66,7 @@ class PluginManager; class AudioFile; class DTMF; class RingBufferPool; +class VideoManager; /** To send multiple string */ typedef std::list<std::string> TokenList; @@ -758,7 +759,6 @@ class Manager { */ std::vector<std::string> loadAccountOrder() const; - private: void removeAccounts(); @@ -961,8 +961,8 @@ class Manager { #ifdef RING_VIDEO std::shared_ptr<video::SinkClient> createSinkClient(const std::string& id="", bool mixer=false); - std::shared_ptr<video::SinkClient> getSinkClient(const std::string& id); + VideoManager& getVideoManager() const { return *videoManager_; } #endif // RING_VIDEO private: @@ -1012,6 +1012,10 @@ class Manager { const std::map<std::string, std::string>& messages, const std::string& from) const noexcept; #endif + +#ifdef RING_VIDEO + std::unique_ptr<VideoManager> videoManager_; +#endif }; // Helper to install a callback to be called once by the main event loop diff --git a/src/media/video/video_rtp_session.cpp b/src/media/video/video_rtp_session.cpp index d00944e8da..49424a3a48 100644 --- a/src/media/video/video_rtp_session.cpp +++ b/src/media/video/video_rtp_session.cpp @@ -73,7 +73,7 @@ void VideoRtpSession::startSender() if (not conference_) { videoLocal_ = getVideoCamera(); - if (auto input = videoManager.videoInput.lock()) { + if (auto input = Manager::instance().getVideoManager().videoInput.lock()) { auto newParams = input->switchInput(input_); try { if (newParams.valid() && diff --git a/src/ring_api.cpp b/src/ring_api.cpp index d43eb3650c..e1fd4125ac 100644 --- a/src/ring_api.cpp +++ b/src/ring_api.cpp @@ -33,6 +33,7 @@ #include "callmanager_interface.h" #include "configurationmanager_interface.h" #include "presencemanager_interface.h" +#include "client/ring_signal.h" #ifdef RING_VIDEO #include "client/videomanager.h" @@ -46,6 +47,11 @@ init(enum InitFlag flags) noexcept ::setDebugMode(flags & DRING_FLAG_DEBUG); ::setConsoleLog(flags & DRING_FLAG_CONSOLE_LOG); + // Following function create a local static variable inside + // This var must have the same live as Manager. + // So we call it now to create this var. + ring::getSignalHandlers(); + try { // current implementation use static variable return &ring::Manager::instance() != nullptr; diff --git a/src/sip/sipcall.cpp b/src/sip/sipcall.cpp index 1d2cfa8ef9..eb858de2db 100644 --- a/src/sip/sipcall.cpp +++ b/src/sip/sipcall.cpp @@ -119,7 +119,7 @@ SIPCall::SIPCall(SIPAccountBase& account, const std::string& id, Call::CallType #ifdef RING_VIDEO // The ID is used to associate video streams to calls , videortp_(id, getVideoSettings()) - , videoInput_(videoManager.videoDeviceMonitor.getMRLForDefaultDevice()) + , videoInput_(Manager::instance().getVideoManager().videoDeviceMonitor.getMRLForDefaultDevice()) #endif , sdp_(new Sdp(id)) { @@ -907,7 +907,7 @@ SIPCall::muteMedia(const std::string& mediaType, bool mute) if (mute == isVideoMuted_) return; RING_WARN("[call:%s] video muting %s", getCallId().c_str(), bool_to_str(mute)); isVideoMuted_ = mute; - videoInput_ = isVideoMuted_ ? "" : videoManager.videoDeviceMonitor.getMRLForDefaultDevice(); + videoInput_ = isVideoMuted_ ? "" : Manager::instance().getVideoManager().videoDeviceMonitor.getMRLForDefaultDevice(); DRing::switchInput(getCallId(), videoInput_); emitSignal<DRing::CallSignal::VideoMuted>(getCallId(), isVideoMuted_); #endif -- GitLab