bang590 / JSPatch

JSPatch bridge Objective-C and Javascript using the Objective-C runtime. You can call any Objective-C class and method in JavaScript by just including a small engine. JSPatch is generally used to hotfix iOS App.
MIT License
11.37k stars 2.24k forks source link

子线程sync到主线程会发生死锁 #847

Closed Tbwas closed 5 years ago

Tbwas commented 5 years ago
dispatch_async_global_queue(function(){
      console.log("00000000000 global queue", require('NSThread').currentThread())

      dispatch_sync_main(function(){ 
            // 想要在主线程做点事情再继续执行....
            console.log("11111111 main queue", require('NSThread').currentThread())
      })
 })

上述代码会发生死锁,不知道是否已知

ApesTalk commented 5 years ago

Same issue here. NSString *js = @"dispatch_async_global_queue(function(){dispatch_sync_main(function(){});});"; [JPEngine evaluateScript:js];

bang590 commented 5 years ago

https://github.com/bang590/JSPatch/blob/master/JSPatch/JPEngine.m#L280 https://github.com/bang590/JSPatch/blob/master/JSPatch/JPEngine.m#L273 见这两行,dispatch_async_global_queue 和 dispatch_sync 都会调 js 函数。

  1. global_queue 执行了 JS,有 js 锁,整个方法执行完才会释放锁
  2. global_queue 里执行了 dispatch_sync,dispatch_sync 里调用 js 函数,需要获得js锁才能继续
  3. 因为 dispatch_sync 是同步方法,不执行完 global_queue 无法释放js锁,造成死锁

解决方法,改成dispatch_async_main