Skip to content

Conversation

@0x1306a94
Copy link
Contributor

@0x1306a94 0x1306a94 commented Jan 7, 2026

问题背景:

  • 鸿蒙的 XComponent 组件每创建一个就会调用 so 的入口函数,对应的 NativeDisplayLink::InitThreadSafeFunction 通过全局变量保存 js_threadsafe_function
  • VSync 回调在独立线程执行,而 NativeDisplayLink::InitThreadSafeFunction 和析构函数在 ArkTS(UI) 线程执行
  • 原本使用普通指针存储 js_threadsafe_function,存在多线程并发访问的数据竞争风险. 之前的 PR 中未考虑到这一点

@codecov-commenter
Copy link

codecov-commenter commented Jan 7, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 77.12%. Comparing base (7464161) to head (cdc4ef9).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3191      +/-   ##
==========================================
- Coverage   77.23%   77.12%   -0.12%     
==========================================
  Files         413      413              
  Lines       21999    21999              
  Branches     6283     6283              
==========================================
- Hits        16991    16966      -25     
- Misses       3799     3807       +8     
- Partials     1209     1226      +17     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@0x1306a94 0x1306a94 force-pushed the fixbug/0x1306a94_ohos_displaylink branch 2 times, most recently from 07e3e8b to 1f2457d Compare January 8, 2026 07:16
@kevingpqi123
Copy link
Collaborator

问题背景:

  • 鸿蒙的 XComponent 组件每创建一个就会调用 so 的入口函数,对应的 NativeDisplayLink::InitThreadSafeFunction 通过全局变量保存 js_threadsafe_function
  • VSync 回调在独立线程执行,而 NativeDisplayLink::InitThreadSafeFunction 和析构函数在 ArkTS(UI) 线程执行
  • 原本使用普通指针存储 js_threadsafe_function,存在多线程并发访问的数据竞争风险. 之前的 PR 中未考虑到这一点

这里的逻辑有些问题,NativeDisplayLink::InitThreadSafeFunction 只需要执行一次获取到 js_threadsafe_function 就可以,js_threadsafe_function 一旦创建,只有当生命周期结束的时候才会去释放,这里不应该存在多线程并发访问的问题,核心点在于保证 NativeDisplayLink::InitThreadSafeFunction 只执行一次吧

@0x1306a94
Copy link
Contributor Author

@kevingpqi123 js_threadsafe_function 创建是和 env 关联的。但是每次 so 的入口函数都会传入一个 env。如果鸿蒙能保证每次初始化传入的 env 都是同一个话,那确实只需要保证创建一次就行了

@kevingpqi123
Copy link
Collaborator

@kevingpqi123 js_threadsafe_function 创建是和 env 关联的。但是每次 so 的入口函数都会传入一个 env。如果鸿蒙能保证每次初始化传入的 env 都是同一个话,那确实只需要保证创建一次就行了

这里 env 的作用就是创建 js_threadsafe_function, 用于创建时绑定 JS 环境,当创建成功后就可以跨线程调用, 后续不再需要创建, napi_call_threadsafe_function 使用的过程中和创建 js_threadsafe_function 时的 env 无关
image

@0x1306a94 0x1306a94 force-pushed the fixbug/0x1306a94_ohos_displaylink branch from 1f2457d to 5ebf49a Compare January 9, 2026 07:57
@0x1306a94 0x1306a94 changed the title Fix thread safety issue in NativeDisplayLink for OHOS by using atomic operations for threadsafe function access. fix(ohos): prevent duplicate initialization of NativeDisplayLink threadsafe function. Jan 9, 2026
@0x1306a94
Copy link
Contributor Author

@kevingpqi123 重新修改了,并使用真机设备测试了页面切换构造多次执行 so 入口函数的场景。
只创建一次是没问题的。也确实和当前的 env 无关。同时修正了之前的 返回值错误

@0x1306a94 0x1306a94 force-pushed the fixbug/0x1306a94_ohos_displaylink branch from 5ebf49a to cdc4ef9 Compare January 9, 2026 09:21
@kevingpqi123
Copy link
Collaborator

可以看下这种实现:
static std::once_flag init_flag;
static napi_threadsafe_function js_threadsafe_function = nullptr;

bool NativeDisplayLink::InitThreadSafeFunction(napi_env env) {
std::call_once(init_flag, & {
napi_value resourceName = nullptr;
napi_create_string_utf8(env, "NativeDisplayLink Safe Function", NAPI_AUTO_LENGTH, &resourceName);
napi_create_threadsafe_function(env, nullptr, nullptr, resourceName, 0, 1,
nullptr, nullptr, nullptr, CallJsFunction,
&js_threadsafe_function);
});
return js_threadsafe_function != nullptr;
}

只初始化一次,天然线程安全,不需要 atomic 操作。
对于 napi_create_threadsafe_function, 如果失败,通常是致命错误,如 env 无效、内存不足等, 重试大概率还是失败, std::call_once 一般够用

@0x1306a94
Copy link
Contributor Author

已修改为 std::call_once 实现

@domchen domchen merged commit b03d5df into Tencent:main Jan 9, 2026
9 checks passed
@0x1306a94 0x1306a94 deleted the fixbug/0x1306a94_ohos_displaylink branch January 9, 2026 13:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants