From 1b4d9aa5eca95da69b4ee5890b295c5578148eac Mon Sep 17 00:00:00 2001 From: Aleksey Kosylo Date: Tue, 19 Mar 2024 13:23:20 +0100 Subject: [PATCH] fix problem with attached(witouth detach) thread --- .../Native/Endpoint/NativeEndpoint.swift | 3 +++ .../Native/Graal/ThreadManager.swift | 18 ++++++++++++++- DXFeedFrameworkTests/PublisherTest.swift | 23 +++++++++++++++++++ Samples/QuoteTableApp/AppDelegate.swift | 1 + 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/DXFeedFramework/Native/Endpoint/NativeEndpoint.swift b/DXFeedFramework/Native/Endpoint/NativeEndpoint.swift index ede4bb22e..cc584c250 100644 --- a/DXFeedFramework/Native/Endpoint/NativeEndpoint.swift +++ b/DXFeedFramework/Native/Endpoint/NativeEndpoint.swift @@ -28,6 +28,9 @@ class NativeEndpoint { private static let listenerCallback: dxfg_endpoint_state_change_listener_func = {_, oldState, newState, context in if let context = context { + ThreadManager.insertPthread() + let currentThread = graal_get_current_thread(Isolate.shared.isolate.pointee) + print("change state \(currentThread) \(pthread_mach_thread_np(pthread_self()))") let endpoint: AnyObject = bridge(ptr: context) if let listener = endpoint as? WeakListener { var old = (try? EnumUtil.valueOf(value: DXEndpointState.convert(oldState))) ?? .notConnected diff --git a/DXFeedFramework/Native/Graal/ThreadManager.swift b/DXFeedFramework/Native/Graal/ThreadManager.swift index 00ea481f4..28316d82a 100644 --- a/DXFeedFramework/Native/Graal/ThreadManager.swift +++ b/DXFeedFramework/Native/Graal/ThreadManager.swift @@ -23,19 +23,27 @@ class ThreadManager { private static let kThreadKey = "GraalThread" private static let key = UnsafeMutablePointer.allocate(capacity: 1) static var str1: String = "" + private static var graalThreads = Set() private init() { pthread_key_create(ThreadManager.key) { pointer in pointer.withMemoryRebound(to: OpaquePointer.self, capacity: 1) { pointer1 in print("deinit thread \(Thread.isMainThread) \(Thread.current) \(Thread.current.threadName) \(pthread_mach_thread_np(pthread_self())) \(pointer1)") + let currentThread = graal_get_current_thread(Isolate.shared.isolate.pointee) // The call to this method has been removed. // In some cases: an attachment to a java thread crashes when you try to use this thread (deinit in this java thread) - graal_detach_thread(pointer1.pointee) + print("pthread_key_create") + if !ThreadManager.containsPthread() { + graal_detach_thread(pointer1.pointee) + } + print("pthread_key_create1") pointer.deallocate() + print("pthread_key_create2") } } } + fileprivate func currentThread() -> OpaquePointer!{ defer { objc_sync_exit(self) @@ -61,6 +69,14 @@ class ThreadManager { return threadPointer } + static func insertPthread() { + graalThreads.insert("\(pthread_mach_thread_np(pthread_self()))") + } + + static func containsPthread() -> Bool { + ThreadManager.graalThreads.contains("\(pthread_mach_thread_np(pthread_self()))") + } + } internal extension Thread { diff --git a/DXFeedFrameworkTests/PublisherTest.swift b/DXFeedFrameworkTests/PublisherTest.swift index 41fa35333..cda55d842 100644 --- a/DXFeedFrameworkTests/PublisherTest.swift +++ b/DXFeedFrameworkTests/PublisherTest.swift @@ -19,6 +19,7 @@ final class PublisherTest: XCTestCase { func testCreatePublisher() throws { try execute() + wait(seconds: 2) } func execute() throws { @@ -41,11 +42,20 @@ final class PublisherTest: XCTestCase { .build() let publisher = endpoint?.getPublisher() let connectedExpectation = expectation(description: "Connected") + DispatchQueue.global(qos: .background).asyncAfter(deadline: .now() + 0.3) { + print("\(pthread_mach_thread_np(pthread_self()))") + print(Thread.current.threadName) + } + DispatchQueue.global(qos: .background).asyncAfter(deadline: .now() + 0.3) { + print("\(pthread_mach_thread_np(pthread_self()))") + print(Thread.current.threadName) + } let stateListener: TestEndpoointStateListener? = TestEndpoointStateListener { listener in listener.callback = { state in if state == .connected { connectedExpectation.fulfill() DispatchQueue.global(qos: .background).asyncAfter(deadline: .now() + 0.3) { + print("\(pthread_mach_thread_np(pthread_self()))") print(Thread.current.threadName) try? publisher?.publish(events: [testQuote]) } @@ -75,4 +85,17 @@ final class PublisherTest: XCTestCase { print("\(error)") } } + + func testDEtachThread() { + // create isolate in main thread + try? SystemProperty.setProperty("test", "test") + + var thread: Thread? = Thread { + // touch graal in background + try? SystemProperty.setProperty("test", "test") + } + thread?.start() + thread = nil + wait(seconds: 2) + } } diff --git a/Samples/QuoteTableApp/AppDelegate.swift b/Samples/QuoteTableApp/AppDelegate.swift index 046be1e93..cbce4878b 100644 --- a/Samples/QuoteTableApp/AppDelegate.swift +++ b/Samples/QuoteTableApp/AppDelegate.swift @@ -12,6 +12,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // var thread: Thread? = Thread { +// var endpoint = try? DXEndpoint.create() // print("execute1 in new thread \(pthread_mach_thread_np(pthread_self()))") // try? SystemProperty.setProperty("test", "test") // try? SystemProperty.setProperty("test", "test")