firebase / firebase/firebase-cpp-sdk

[Bug] Deadlock in firebase::auth::IdTokenRefreshThread

オープン
#1,445 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る
api: auth new type: question
主要言語
C++
スター
326
フォーク
137
平均マージ
3日 9時間
マージ済み PR(30日)
5

説明

### [REQUIRED] Please fill in the following fields:

* Pre-built SDK from the [website](https://firebase.google.com/download/cpp) or open-source from this repo: open-source from this repo
* Firebase C++ SDK version: 11.4.0
* Problematic Firebase Component: auth
* Other Firebase Components in use: database
* Platform you are using the C++ SDK on: Mac, Windows
* Platform you are targeting: desktop

### [REQUIRED] Please describe the issue here:
Deadlock in IdTokenRefreshThread which causes the entire app to hang, e.g., Database cannot be safely deleted since it is deadlocked on destruction by waiting IdTokenRefreshThread to finish

1. IdTokenRefreshThread holds `refresh_thread->ref_count_mutex_` and `auth->auth_data_->future_impl.mutex()`. Then it accesses `refresh_thread->token_refresh_listener_.GetTokenTimestamp()` which has its own mutex
```
#0 firebase::auth::IdTokenRefreshThread::Initialize(firebase::auth::AuthData*)::$_4::operator()(firebase::auth::IdTokenRefreshThread*) const at /Users/venhe/tmp/Firebase/Firebase/auth/src/desktop/auth_desktop.cc:818
#1 firebase::auth::IdTokenRefreshThread::Initialize(firebase::auth::AuthData*)::$_4::__invoke(firebase::auth::IdTokenRefreshThread*) at /Users/venhe/tmp/Firebase/Firebase/auth/src/desktop/auth_desktop.cc:805
```

2. Another worker thread fires an event about token change. `IdTokenRefreshListener::OnIdTokenChanged` locks its own mutex first and then `auth->auth_data_->future_impl.mutex()`
```
#0 firebase::auth::IdTokenRefreshListener::OnIdTokenChanged(firebase::auth::Auth*) at /Users/venhe/tmp/Firebase/Firebase/auth/src/desktop/auth_desktop.cc:135
#1 firebase::auth::NotifyIdTokenListeners(firebase::auth::AuthData*) at /Users/venhe/tmp/Firebase/Firebase/auth/src/auth.cc:362
#2 0firebase::auth::AuthenticationResult::SetAsCurrentUser(firebase::auth::AuthData*) const at /Users/venhe/tmp/Firebase/Firebase/auth/src/desktop/authentication_result.cc:64
#3 void firebase::auth::PerformSignInFlow(firebase::auth::AuthDataHandle*) at /Users/venhe/tmp/Firebase/Firebase/auth/src/desktop/sign_in_flow.h:125
```

Deadlock happens if IdTokenRefreshThread just about to call `GetTokenTimestamp` and if IdTokenRefreshListener::OnIdTokenChanged successfully acquired its mutex.

#### Steps to reproduce:

Hard to reproduce, but happens quite often.

What happened? How can we make the problem occur?

Simulate it, e.g., call IdTokenRefreshListener::OnIdTokenChanged in a loop, and it will definitely deadlock at some point

If you have a downloadable sample project that reproduces the bug you're reporting, you will
likely receive a faster response on your issue.

コントリビューションガイド

コントリビューションガイドを開く

調査の方向性

auth/src/desktop/auth_desktop.cc の IdTokenRefreshThread::Initialize(805-818 行付近)と、135 行目の IdTokenRefreshListener::OnIdTokenChanged から始め、auth/src/auth.cc、authentication_result.cc、sign_in_flow.h にある関連する呼び出しを追跡します。OnIdTokenChanged を繰り返し呼び出して報告された順序を再現し、競合する mutex の取得を調べます。シミュレートした race でデッドロックが発生しなくなり、application または Database の破棄を完了できれば完了です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
cpp
領域
authentication, databases
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
停滞
明瞭さ
説明が足りない
初心者へのやさしさ
30/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。