Skip to content
Snippets Groups Projects
Commit 8dcbbc38 authored by Mohamed Chibani's avatar Mohamed Chibani
Browse files

audio layer: prevent a deadlock

A deadlock is caused by a lock-order-inversion of the private
mutex from pulse-audio thread loop, and the callMutex_ mutex
from the Call class. It occurs when concurrently calling
writeToSpeaker() and onNegoDone() callbacks.
The deadlock is prevented by avoid to a access Call data from
the pulse-audio thread.

Gitlab: #623

Change-Id: I91d936b37528db3de24e93b0d49d686f5ca11813
parent a850889b
No related branches found
No related tags found
No related merge requests found
...@@ -615,6 +615,9 @@ void ...@@ -615,6 +615,9 @@ void
Manager::ManagerPimpl::addWaitingCall(const std::string& id) Manager::ManagerPimpl::addWaitingCall(const std::string& id)
{ {
std::lock_guard<std::mutex> m(waitingCallsMutex_); std::lock_guard<std::mutex> m(waitingCallsMutex_);
// Enable incoming call beep if needed.
if (audiodriver_ and waitingCalls_.empty() and not currentCall_.empty())
audiodriver_->playIncomingCallNotification(true);
waitingCalls_.insert(id); waitingCalls_.insert(id);
} }
...@@ -623,6 +626,8 @@ Manager::ManagerPimpl::removeWaitingCall(const std::string& id) ...@@ -623,6 +626,8 @@ Manager::ManagerPimpl::removeWaitingCall(const std::string& id)
{ {
std::lock_guard<std::mutex> m(waitingCallsMutex_); std::lock_guard<std::mutex> m(waitingCallsMutex_);
waitingCalls_.erase(id); waitingCalls_.erase(id);
if (audiodriver_ and waitingCalls_.empty())
audiodriver_->playIncomingCallNotification(false);
} }
void void
......
...@@ -164,21 +164,17 @@ AudioLayer::putUrgent(AudioBuffer& buffer) ...@@ -164,21 +164,17 @@ AudioLayer::putUrgent(AudioBuffer& buffer)
void void
AudioLayer::notifyIncomingCall() AudioLayer::notifyIncomingCall()
{ {
if (!Manager::instance().incomingCallsWaiting()) if (not playIncomingCallBeep_)
return; return;
auto now = std::chrono::system_clock::now(); auto now = std::chrono::system_clock::now();
// Notify maximum once every 5 seconds // Notify maximum once every 5 seconds
if ((now - lastNotificationTime_) < std::chrono::seconds(5)) if (now < lastNotificationTime_ + std::chrono::seconds(5))
return; return;
lastNotificationTime_ = now; lastNotificationTime_ = now;
// Enable notification only if more than one call
if (!Manager::instance().hasCurrentCall())
return;
Tone tone("440/160", getSampleRate()); Tone tone("440/160", getSampleRate());
size_t nbSample = tone.getSize(); size_t nbSample = tone.getSize();
AudioBuffer buf(nbSample, AudioFormat::MONO()); AudioBuffer buf(nbSample, AudioFormat::MONO());
......
...@@ -117,6 +117,12 @@ public: ...@@ -117,6 +117,12 @@ public:
*/ */
void putUrgent(AudioBuffer& buffer); void putUrgent(AudioBuffer& buffer);
/**
* Start/Stop playing the incoming call notification sound (beep)
* while playing back audio (typically during an ongoing call).
*/
void playIncomingCallNotification(bool play) { playIncomingCallBeep_.exchange(play); }
/** /**
* Flush main buffer * Flush main buffer
*/ */
...@@ -179,7 +185,7 @@ public: ...@@ -179,7 +185,7 @@ public:
AudioFormat getFormat() const { return audioFormat_; } AudioFormat getFormat() const { return audioFormat_; }
/** /**
* Emit an audio notification on incoming calls * Emit an audio notification (beep) on incoming calls
*/ */
void notifyIncomingCall(); void notifyIncomingCall();
...@@ -295,10 +301,15 @@ protected: ...@@ -295,10 +301,15 @@ protected:
private: private:
void checkAEC(); void checkAEC();
// Set to "true" to play the incoming call notification (beep)
// when the playback is on (typically when there is already an
// active call).
std::atomic_bool playIncomingCallBeep_ {false};
/** /**
* Time of the last incoming call notification * Time of the last incoming call notification
*/ */
std::chrono::system_clock::time_point lastNotificationTime_; std::chrono::system_clock::time_point lastNotificationTime_ {
std::chrono::system_clock::time_point::min()};
}; };
} // namespace jami } // namespace jami
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment