Fix race condition in Android camera JNI code.

AndroidVideoCapturerJni dtor is called on signaling thread
and may destroy JNI global refs while processing late camera
frame arrival in ReturnBuffer_w() in worker thread.

Fix this by waiting for all function invoked on worker thread
to complete in camera JNI dtor.

R=wzh@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/49099004

Cr-Commit-Position: refs/heads/master@{#9037}
This commit is contained in:
Alex Glaznev
2015-04-20 16:54:42 -07:00
parent ac7d97fea6
commit c4905fb72a
2 changed files with 17 additions and 4 deletions

View File

@@ -68,7 +68,9 @@ AndroidVideoCapturerJni::AndroidVideoCapturerJni(JNIEnv* jni,
jni,
FindClass(jni,
"org/webrtc/VideoCapturerAndroid$NativeObserver")),
capturer_(nullptr) {
capturer_(nullptr),
thread_(nullptr),
valid_global_refs_(true) {
LOG(LS_INFO) << "AndroidVideoCapturerJni ctor";
thread_checker_.DetachFromThread();
}
@@ -84,7 +86,12 @@ bool AndroidVideoCapturerJni::Init(jstring device_name) {
}
AndroidVideoCapturerJni::~AndroidVideoCapturerJni() {
LOG(LS_INFO) << "AndroidVideoCapturerJni dtor";
valid_global_refs_ = false;
if (thread_ != nullptr) {
LOG(LS_INFO) << "AndroidVideoCapturerJni dtor - flush invoker";
invoker_.Flush(thread_);
}
LOG(LS_INFO) << "AndroidVideoCapturerJni dtor done";
}
void AndroidVideoCapturerJni::Start(int width, int height, int framerate,
@@ -136,6 +143,10 @@ void AndroidVideoCapturerJni::ReturnBuffer(int64 time_stamp) {
}
void AndroidVideoCapturerJni::ReturnBuffer_w(int64 time_stamp) {
if (!valid_global_refs_) {
LOG(LS_ERROR) << "ReturnBuffer_w is called for invalid global refs.";
return;
}
jmethodID m = GetMethodID(jni(), *j_video_capturer_class_,
"returnBuffer", "(J)V");
jni()->CallVoidMethod(*j_capturer_global_, m, time_stamp);
@@ -174,7 +185,7 @@ void AndroidVideoCapturerJni::OnCapturerStarted_w(bool success) {
if (capturer_) {
capturer_->OnCapturerStarted(success);
} else {
LOG(LS_ERROR) << "OnCapturerStarted_w is called for null capturer.";
LOG(LS_WARNING) << "OnCapturerStarted_w is called for closed capturer.";
}
}
@@ -187,7 +198,8 @@ void AndroidVideoCapturerJni::OnIncomingFrame_w(void* video_frame,
capturer_->OnIncomingFrame(video_frame, length, rotation, time_stamp);
} else {
LOG(LS_INFO) <<
"Frame arrived after camera has been stopped: " << time_stamp;
"Frame arrived after camera has been stopped: " << time_stamp <<
". Valid global refs: " << valid_global_refs_;
ReturnBuffer_w(time_stamp);
}
}

View File

@@ -86,6 +86,7 @@ private:
const ScopedGlobalRef<jobject> j_capturer_global_;
const ScopedGlobalRef<jclass> j_video_capturer_class_;
const ScopedGlobalRef<jclass> j_observer_class_;
volatile bool valid_global_refs_;
jobject j_frame_observer_;
rtc::ThreadChecker thread_checker_;