Skip to content

Commit a84a7b5

Browse files
authored
Merge pull request #94 from sagebind/fix-deadlock-on-ondestroy
Fix deadlock on activity onDestroy
2 parents 0f00a58 + a9e91f4 commit a84a7b5

File tree

1 file changed

+32
-7
lines changed
  • android-activity/src/native_activity

1 file changed

+32
-7
lines changed

android-activity/src/native_activity/glue.rs

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,18 @@ impl NativeActivityGlue {
199199
}
200200
}
201201

202+
/// The status of the native thread that's created to run
203+
/// `android_main`
204+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
205+
pub enum NativeThreadState {
206+
/// The `android_main` thread hasn't been created yet
207+
Init,
208+
/// The `android_main` thread has been spawned and started running
209+
Running,
210+
/// The `android_main` thread has finished
211+
Stopped,
212+
}
213+
202214
#[derive(Debug)]
203215
pub struct NativeActivityState {
204216
pub msg_read: libc::c_int,
@@ -210,8 +222,11 @@ pub struct NativeActivityState {
210222
pub content_rect: ndk_sys::ARect,
211223
pub activity_state: State,
212224
pub destroy_requested: bool,
213-
pub running: bool,
225+
pub thread_state: NativeThreadState,
214226
pub app_has_saved_state: bool,
227+
228+
/// Set as soon as the Java main thread notifies us of an
229+
/// `onDestroyed` callback.
215230
pub destroyed: bool,
216231
pub redraw_needed: bool,
217232
pub pending_input_queue: *mut ndk_sys::AInputQueue,
@@ -303,8 +318,6 @@ impl Drop for WaitableNativeActivityState {
303318
unsafe {
304319
let mut guard = self.mutex.lock().unwrap();
305320
guard.detach_input_queue_from_looper();
306-
guard.destroyed = true;
307-
self.cond.notify_one();
308321
}
309322
}
310323
}
@@ -356,7 +369,7 @@ impl WaitableNativeActivityState {
356369
content_rect: Rect::empty().into(),
357370
activity_state: State::Init,
358371
destroy_requested: false,
359-
running: false,
372+
thread_state: NativeThreadState::Init,
360373
app_has_saved_state: false,
361374
destroyed: false,
362375
redraw_needed: false,
@@ -369,10 +382,11 @@ impl WaitableNativeActivityState {
369382

370383
pub fn notify_destroyed(&self) {
371384
let mut guard = self.mutex.lock().unwrap();
385+
guard.destroyed = true;
372386

373387
unsafe {
374388
guard.write_cmd(AppCmd::Destroy);
375-
while !guard.destroyed {
389+
while guard.thread_state != NativeThreadState::Stopped {
376390
guard = self.cond.wait(guard).unwrap();
377391
}
378392

@@ -541,7 +555,13 @@ impl WaitableNativeActivityState {
541555

542556
pub fn notify_main_thread_running(&self) {
543557
let mut guard = self.mutex.lock().unwrap();
544-
guard.running = true;
558+
guard.thread_state = NativeThreadState::Running;
559+
self.cond.notify_one();
560+
}
561+
562+
pub fn notify_main_thread_stopped_running(&self) {
563+
let mut guard = self.mutex.lock().unwrap();
564+
guard.thread_state = NativeThreadState::Stopped;
545565
self.cond.notify_one();
546566
}
547567

@@ -907,11 +927,16 @@ extern "C" fn ANativeActivity_onCreate(
907927

908928
ndk_context::release_android_context();
909929
}
930+
931+
rust_glue.notify_main_thread_stopped_running();
910932
});
911933

912934
// Wait for thread to start.
913935
let mut guard = jvm_glue.mutex.lock().unwrap();
914-
while !guard.running {
936+
937+
// Don't specifically wait for `Running` just in case `android_main` returns
938+
// immediately and the state is set to `Stopped`
939+
while guard.thread_state == NativeThreadState::Init {
915940
guard = jvm_glue.cond.wait(guard).unwrap();
916941
}
917942
})

0 commit comments

Comments
 (0)