Skip to content

Commit 4e7dcb9

Browse files
committed
Thread detach hook for Java JNI on Android
1 parent 56f36b6 commit 4e7dcb9

File tree

3 files changed

+40
-0
lines changed

3 files changed

+40
-0
lines changed

private/queue_private.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,20 @@ void
323323
dispatch_async_enforce_qos_class_f(dispatch_queue_t queue,
324324
void *_Nullable context, dispatch_function_t work);
325325

326+
#ifdef __ANDROID__
327+
/*!
328+
* @function _dispatch_install_thread_detach_callback
329+
*
330+
* @param callback
331+
* Function to be called before each worker thread exits to detach JVM.
332+
*
333+
* Hook to be able to detach threads from the Java JVM before they exit.
334+
* If JNI has been used on a thread on Android it needs to have been
335+
* "detached" before the thread exits or the application will crash.
336+
*/
337+
DISPATCH_EXPORT
338+
void _dispatch_install_thread_detach_callback(dispatch_function_t cb);
339+
#endif
326340

327341
__END_DECLS
328342

src/queue.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -885,6 +885,18 @@ gettid(void)
885885
if ((f) && tsd->k) ((void(*)(void*))(f))(tsd->k); \
886886
} while (0)
887887

888+
#ifdef __ANDROID__
889+
static void (*_dispatch_thread_detach_callback)(void);
890+
891+
void
892+
_dispatch_install_thread_detach_callback(dispatch_function_t cb)
893+
{
894+
if (os_atomic_xchg(&_dispatch_thread_detach_callback, cb, relaxed)) {
895+
DISPATCH_CLIENT_CRASH(0, "Installing a thread detach callback twice");
896+
}
897+
}
898+
#endif
899+
888900
void
889901
_libdispatch_tsd_cleanup(void *ctx)
890902
{
@@ -909,6 +921,11 @@ _libdispatch_tsd_cleanup(void *ctx)
909921
_tsd_call_cleanup(dispatch_voucher_key, _voucher_thread_cleanup);
910922
_tsd_call_cleanup(dispatch_deferred_items_key,
911923
_dispatch_deferred_items_cleanup);
924+
#ifdef __ANDROID__
925+
if (_dispatch_thread_detach_callback) {
926+
_dispatch_thread_detach_callback();
927+
}
928+
#endif
912929
tsd->tid = 0;
913930
}
914931

src/swift/Queue.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,15 @@ public extension DispatchQueue {
330330
let p = v.flatMap { Unmanaged.passRetained($0).toOpaque() }
331331
dispatch_queue_set_specific(self.__wrapped, k, p, _destructDispatchSpecificValue)
332332
}
333+
334+
#if os(Android)
335+
@_silgen_name("_dispatch_install_thread_detach_callback")
336+
private static func _dispatch_install_thread_detach_callback(_ cb: @escaping @convention(c) () -> Void)
337+
338+
public static func setThreadDetachCallback(_ cb: @escaping @convention(c) () -> Void) {
339+
_dispatch_install_thread_detach_callback(cb)
340+
}
341+
#endif
333342
}
334343

335344
private func _destructDispatchSpecificValue(ptr: UnsafeMutableRawPointer?) {

0 commit comments

Comments
 (0)