forked from osmocom/wireshark
Fix: Fixed issue with deadlock when same RTP dialog opened twice
RTP dialogs can stay opened, therefore calls of its functions are protected by locks. There was issue that same mutex was used during construction of the dialog and calling functions. It created possible deadlock. Change separates lock used for dialog creation and lock for function calls. When function call lock is locked, new calls are ignored and warning is printed to STDERR. Showing a dialog with warning looks too intrusive to me. Fixes #18025
This commit is contained in:
parent
0e269659ec
commit
411b3c1d78
|
@ -240,11 +240,12 @@ enum {
|
|||
};
|
||||
|
||||
RtpAnalysisDialog *RtpAnalysisDialog::pinstance_{nullptr};
|
||||
std::mutex RtpAnalysisDialog::mutex_;
|
||||
std::mutex RtpAnalysisDialog::init_mutex_;
|
||||
std::mutex RtpAnalysisDialog::run_mutex_;
|
||||
|
||||
RtpAnalysisDialog *RtpAnalysisDialog::openRtpAnalysisDialog(QWidget &parent, CaptureFile &cf, QObject *packet_list)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(init_mutex_);
|
||||
if (pinstance_ == nullptr)
|
||||
{
|
||||
pinstance_ = new RtpAnalysisDialog(parent, cf);
|
||||
|
@ -316,13 +317,15 @@ RtpAnalysisDialog::RtpAnalysisDialog(QWidget &parent, CaptureFile &cf) :
|
|||
|
||||
RtpAnalysisDialog::~RtpAnalysisDialog()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(init_mutex_);
|
||||
if (pinstance_ != nullptr) {
|
||||
delete ui;
|
||||
for(int i=0; i<tabs_.count(); i++) {
|
||||
deleteTabInfo(tabs_[i]);
|
||||
g_free(tabs_[i]);
|
||||
}
|
||||
pinstance_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void RtpAnalysisDialog::deleteTabInfo(tab_info_t *tab_info)
|
||||
|
@ -1025,7 +1028,8 @@ void RtpAnalysisDialog::showStreamMenu(QPoint pos)
|
|||
|
||||
void RtpAnalysisDialog::replaceRtpStreams(QVector<rtpstream_id_t *> stream_ids)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::unique_lock<std::mutex> lock(run_mutex_, std::try_to_lock);
|
||||
if (lock.owns_lock()) {
|
||||
// Delete existing tabs (from last to first)
|
||||
if (tabs_.count() > 0) {
|
||||
for(int i = static_cast<int>(tabs_.count()); i>0; i--) {
|
||||
|
@ -1033,12 +1037,19 @@ void RtpAnalysisDialog::replaceRtpStreams(QVector<rtpstream_id_t *> stream_ids)
|
|||
}
|
||||
}
|
||||
addRtpStreamsPrivate(stream_ids);
|
||||
} else {
|
||||
ws_warning("replaceRtpStreams was called while other thread locked it. Current call is ignored, try it later.");
|
||||
}
|
||||
}
|
||||
|
||||
void RtpAnalysisDialog::addRtpStreams(QVector<rtpstream_id_t *> stream_ids)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::unique_lock<std::mutex> lock(run_mutex_, std::try_to_lock);
|
||||
if (lock.owns_lock()) {
|
||||
addRtpStreamsPrivate(stream_ids);
|
||||
} else {
|
||||
ws_warning("addRtpStreams was called while other thread locked it. Current call is ignored, try it later.");
|
||||
}
|
||||
}
|
||||
|
||||
void RtpAnalysisDialog::addRtpStreamsPrivate(QVector<rtpstream_id_t *> stream_ids)
|
||||
|
@ -1089,7 +1100,8 @@ void RtpAnalysisDialog::addRtpStreamsPrivate(QVector<rtpstream_id_t *> stream_id
|
|||
|
||||
void RtpAnalysisDialog::removeRtpStreams(QVector<rtpstream_id_t *> stream_ids)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::unique_lock<std::mutex> lock(run_mutex_, std::try_to_lock);
|
||||
if (lock.owns_lock()) {
|
||||
setUpdatesEnabled(false);
|
||||
foreach(rtpstream_id_t *id, stream_ids) {
|
||||
QList<tab_info_t *> tabs = tab_hash_.values(rtpstream_id_to_hash(id));
|
||||
|
@ -1103,6 +1115,9 @@ void RtpAnalysisDialog::removeRtpStreams(QVector<rtpstream_id_t *> stream_ids)
|
|||
setUpdatesEnabled(true);
|
||||
|
||||
updateGraph();
|
||||
} else {
|
||||
ws_warning("removeRtpStreams was called while other thread locked it. Current call is ignored, try it later.");
|
||||
}
|
||||
}
|
||||
|
||||
tab_info_t *RtpAnalysisDialog::getTabInfoForCurrentTab()
|
||||
|
|
|
@ -127,7 +127,8 @@ private slots:
|
|||
|
||||
private:
|
||||
static RtpAnalysisDialog *pinstance_;
|
||||
static std::mutex mutex_;
|
||||
static std::mutex init_mutex_;
|
||||
static std::mutex run_mutex_;
|
||||
|
||||
Ui::RtpAnalysisDialog *ui;
|
||||
enum StreamDirection { dir_all_, dir_one_ };
|
||||
|
|
|
@ -134,11 +134,12 @@ public:
|
|||
};
|
||||
|
||||
RtpPlayerDialog *RtpPlayerDialog::pinstance_{nullptr};
|
||||
std::mutex RtpPlayerDialog::mutex_;
|
||||
std::mutex RtpPlayerDialog::init_mutex_;
|
||||
std::mutex RtpPlayerDialog::run_mutex_;
|
||||
|
||||
RtpPlayerDialog *RtpPlayerDialog::openRtpPlayerDialog(QWidget &parent, CaptureFile &cf, QObject *packet_list, bool capture_running)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(init_mutex_);
|
||||
if (pinstance_ == nullptr)
|
||||
{
|
||||
pinstance_ = new RtpPlayerDialog(parent, cf, capture_running);
|
||||
|
@ -377,7 +378,8 @@ QToolButton *RtpPlayerDialog::addPlayerButton(QDialogButtonBox *button_box, QDia
|
|||
#ifdef QT_MULTIMEDIA_LIB
|
||||
RtpPlayerDialog::~RtpPlayerDialog()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(init_mutex_);
|
||||
if (pinstance_ != nullptr) {
|
||||
cleanupMarkerStream();
|
||||
for (int row = 0; row < ui->streamTreeWidget->topLevelItemCount(); row++) {
|
||||
QTreeWidgetItem *ti = ui->streamTreeWidget->topLevelItem(row);
|
||||
|
@ -387,6 +389,7 @@ RtpPlayerDialog::~RtpPlayerDialog()
|
|||
}
|
||||
delete ui;
|
||||
pinstance_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void RtpPlayerDialog::accept()
|
||||
|
@ -773,7 +776,8 @@ void RtpPlayerDialog::unlockUI()
|
|||
|
||||
void RtpPlayerDialog::replaceRtpStreams(QVector<rtpstream_id_t *> stream_ids)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::unique_lock<std::mutex> lock(run_mutex_, std::try_to_lock);
|
||||
if (lock.owns_lock()) {
|
||||
lockUI();
|
||||
|
||||
// Delete all existing rows
|
||||
|
@ -797,11 +801,15 @@ void RtpPlayerDialog::replaceRtpStreams(QVector<rtpstream_id_t *> stream_ids)
|
|||
#ifdef QT_MULTIMEDIA_LIB
|
||||
QTimer::singleShot(0, this, SLOT(retapPackets()));
|
||||
#endif
|
||||
} else {
|
||||
ws_warning("replaceRtpStreams was called while other thread locked it. Current call is ignored, try it later.");
|
||||
}
|
||||
}
|
||||
|
||||
void RtpPlayerDialog::addRtpStreams(QVector<rtpstream_id_t *> stream_ids)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::unique_lock<std::mutex> lock(run_mutex_, std::try_to_lock);
|
||||
if (lock.owns_lock()) {
|
||||
lockUI();
|
||||
|
||||
int tli_count = ui->streamTreeWidget->topLevelItemCount();
|
||||
|
@ -819,11 +827,15 @@ void RtpPlayerDialog::addRtpStreams(QVector<rtpstream_id_t *> stream_ids)
|
|||
#ifdef QT_MULTIMEDIA_LIB
|
||||
QTimer::singleShot(0, this, SLOT(retapPackets()));
|
||||
#endif
|
||||
} else {
|
||||
ws_warning("addRtpStreams was called while other thread locked it. Current call is ignored, try it later.");
|
||||
}
|
||||
}
|
||||
|
||||
void RtpPlayerDialog::removeRtpStreams(QVector<rtpstream_id_t *> stream_ids)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::unique_lock<std::mutex> lock(run_mutex_, std::try_to_lock);
|
||||
if (lock.owns_lock()) {
|
||||
lockUI();
|
||||
int tli_count = ui->streamTreeWidget->topLevelItemCount();
|
||||
|
||||
|
@ -842,6 +854,9 @@ void RtpPlayerDialog::removeRtpStreams(QVector<rtpstream_id_t *> stream_ids)
|
|||
|
||||
updateWidgets();
|
||||
unlockUI();
|
||||
} else {
|
||||
ws_warning("removeRtpStreams was called while other thread locked it. Current call is ignored, try it later.");
|
||||
}
|
||||
}
|
||||
|
||||
void RtpPlayerDialog::setMarkers()
|
||||
|
|
|
@ -202,7 +202,8 @@ private slots:
|
|||
#endif
|
||||
private:
|
||||
static RtpPlayerDialog *pinstance_;
|
||||
static std::mutex mutex_;
|
||||
static std::mutex init_mutex_;
|
||||
static std::mutex run_mutex_;
|
||||
|
||||
#ifdef QT_MULTIMEDIA_LIB
|
||||
Ui::RtpPlayerDialog *ui;
|
||||
|
|
|
@ -44,11 +44,11 @@ enum { voip_calls_type_ = 1000 };
|
|||
|
||||
VoipCallsDialog *VoipCallsDialog::pinstance_voip_{nullptr};
|
||||
VoipCallsDialog *VoipCallsDialog::pinstance_sip_{nullptr};
|
||||
std::mutex VoipCallsDialog::mutex_;
|
||||
std::mutex VoipCallsDialog::init_mutex_;
|
||||
|
||||
VoipCallsDialog *VoipCallsDialog::openVoipCallsDialogVoip(QWidget &parent, CaptureFile &cf, QObject *packet_list)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(init_mutex_);
|
||||
if (pinstance_voip_ == nullptr)
|
||||
{
|
||||
pinstance_voip_ = new VoipCallsDialog(parent, cf, false);
|
||||
|
@ -60,7 +60,7 @@ VoipCallsDialog *VoipCallsDialog::openVoipCallsDialogVoip(QWidget &parent, Captu
|
|||
|
||||
VoipCallsDialog *VoipCallsDialog::openVoipCallsDialogSip(QWidget &parent, CaptureFile &cf, QObject *packet_list)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(init_mutex_);
|
||||
if (pinstance_sip_ == nullptr)
|
||||
{
|
||||
pinstance_sip_ = new VoipCallsDialog(parent, cf, true);
|
||||
|
@ -195,7 +195,10 @@ bool VoipCallsDialog::eventFilter(QObject *, QEvent *event)
|
|||
|
||||
VoipCallsDialog::~VoipCallsDialog()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(init_mutex_);
|
||||
if ((all_flows_ && (pinstance_sip_ != nullptr))
|
||||
|| (!all_flows_ && (pinstance_voip_ != nullptr))
|
||||
) {
|
||||
delete ui;
|
||||
|
||||
voip_calls_reset_all_taps(&tapinfo_);
|
||||
|
@ -214,6 +217,7 @@ VoipCallsDialog::~VoipCallsDialog()
|
|||
} else {
|
||||
pinstance_voip_ = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VoipCallsDialog::removeTapListeners()
|
||||
|
|
|
@ -89,7 +89,7 @@ private:
|
|||
static VoipCallsDialog *pinstance_voip_;
|
||||
static VoipCallsDialog *pinstance_sip_;
|
||||
bool all_flows_;
|
||||
static std::mutex mutex_;
|
||||
static std::mutex init_mutex_;
|
||||
|
||||
Ui::VoipCallsDialog *ui;
|
||||
VoipCallsInfoModel *call_infos_model_;
|
||||
|
|
Loading…
Reference in New Issue