HarmonyOS 使用taskPool引起崩溃?

HarmonyOS 使用taskPool引起崩溃?

有一个解压缩的操作想放到子线程执行,使用pako来解压:

@Concurrent 
export async function doInflate(data: Uint8Array): Promise<Uint8Array> { 
  let pako: ESObject = await import('pako') 
  let res: Uint8Array = pako.inflate(data) 
  return res 
}

在主线程执行:taskpool.execute(doInflate, data)。大概有10个文件,只会在一开始将每个文件解压一次,后续不会再执行这个解压操作。一开始运行正常,但是持续运行4分钟左右就会出现崩溃。如果把这个解压操作放在主线程就不会崩溃。从日志看起来,是OS_TaskWorker线程崩了。监控发现内存很稳定也没有一直涨。这是什么原因引起的崩溃。
hilog崩溃日志如下:

04-12 14:57:38.755   31626-31693  C03F00/MUSL-SIGCHAIN           com.test.demo          E     signal_chain_handler call 2 rd sigchain action for signal: 11 
04-12 14:57:38.923   31626-31635  C057C7/BinderConnector         com.test.demo          E     [nodict]WriteBinder 491: ioctl_binder returned EINTR 
04-12 14:57:38.929   31626-31636  C057C7/BinderConnector         com.test.demo          E     [nodict]WriteBinder 491: ioctl_binder returned EINTR 
04-12 14:57:38.934   31626-31640  C057C7/BinderConnector         com.test.demo          E     [nodict]WriteBinder 491: ioctl_binder returned EINTR 
04-12 14:57:38.947   31626-31667  C057C7/BinderConnector         com.test.demo          E     [nodict]WriteBinder 491: ioctl_binder returned EINTR 
04-12 14:57:39.894   31626-31693  C03F00/MUSL-SIGCHAIN           com.test.demo          E     signal_chain_handler call usr sigaction for signal: 11 
04-12 14:57:39.897   31626-35429  C01719/ffrt                    com.test.demo          E     [nodict]<<<=== ffrt black box(BBOX) start ===>>> 
  04-12 14:57:39.897   31626-35429  C01719/ffrt                    com.test.demo          E     [nodict]<<<=== current status ===>>> 
  04-12 14:57:39.897   31626-35429  C01719/ffrt                    com.test.demo          E     [nodict]<<<=== task counter ===>>> 
  04-12 14:57:39.897   31626-35429  C01719/ffrt                    com.test.demo          E     [nodict]FFRT BBOX TaskSubmitCounter:1600 TaskEnQueueCounter:1600 TaskDoneCounter:916 
04-12 14:57:39.897   31626-35429  C01719/ffrt                    com.test.demo          E     [nodict]FFRT BBOX TaskRunCounter:1954 TaskSwitchCounter:354 TaskFinishCounter:1600 
04-12 14:57:39.897   31626-35429  C01719/ffrt                    com.test.demo          E     [nodict]FFRT BBOX TaskWakeCounterInc:0, TaskPendingCounter:0 
04-12 14:57:39.897   31626-35429  C01719/ffrt                    com.test.demo          E     [nodict]TaskRunCounter equals TaskSwitchCounter + TaskFinishCounter 
04-12 14:57:39.897   31626-35429  C01719/ffrt                    com.test.demo          E     [nodict]<<<=== worker status ===>>> 
  04-12 14:57:39.897   31626-35429  C01719/ffrt                    com.test.demo          E     [nodict]<<<=== ready queue status ===>>> 
  04-12 14:57:39.897   31626-35429  C01719/ffrt                    com.test.demo          E     [nodict]<<<=== ffrt black box(BBOX) finish ===>>> 
  04-12 14:57:39.898   31626-31693  C03F00/MUSL-SIGCHAIN           com.test.demo          E     signal_chain_handler call 2 rd sigchain action for signal: 11 
04-12 14:57:39.898   31626-31693  C03F00/MUSL-SIGCHAIN           com.test.demo          E     signal_chain_handler SIG_DFL handler for signal: 11 
04-12 14:57:39.899   31626-31693  C03F00/MUSL-SIGCHAIN           com.test.demo          E     pid(31626) rethrow sig(11) success.
阅读 833
avatarAI BotBETA

问题分析

从您提供的日志信息来看,崩溃与信号 11(SIGSEGV,即段错误)有关,这通常表明程序试图访问它没有权限访问的内存区域。在您的情况下,这个错误发生在 OS_TaskWorker 线程中,这个线程是由 HarmonyOS 的 taskPool 管理的。

可能的原因

  1. 内存访问错误

    • pako.inflate 函数在处理 Uint8Array 时可能由于某些原因(如数组越界、内存损坏等)访问了非法内存。
    • 由于此函数在子线程中执行,任何与内存管理相关的错误(如内存泄漏、双重释放等)都可能导致此类崩溃。
  2. 异步编程问题

    • 您的 doInflate 函数使用了 async/await 语法,这意味着它可能涉及到 JavaScript 的 Promise 和事件循环。在 HarmonyOS 的多线程环境中,如果 Promise 的解析或拒绝处理不当,可能会引发问题。
    • 动态模块加载(await import('pako'))在子线程中可能行为不如预期,尤其是如果模块或其依赖项在多个线程中共享或未正确初始化。
  3. HarmonyOS 特定问题

    • HarmonyOS 的 taskPool 和线程管理可能与标准的 JavaScript 运行时有所不同,特别是当涉及到模块加载和异步操作时。
    • HarmonyOS 的内存管理策略和限制可能影响了子线程中的内存访问。

解决建议

  1. 验证和测试 pako 库

    • 确保 pako.inflate 函数在单线程环境中正常工作,并且处理的数据没有超出其预期范围。
    • 尝试使用静态导入 pako 而不是动态导入,以查看这是否影响行为。
  2. 优化内存管理

    • 检查您的代码是否有可能导致内存泄漏的地方,尤其是在处理大量数据或频繁分配内存时。
    • 确保在不再需要时正确释放或清理内存。
  3. 使用 try-catch 捕获异常

    • doInflate 函数中添加 try-catch 块来捕获并处理任何可能抛出的异常,这有助于识别问题发生的具体位置。
  4. 简化异步处理

    • 如果可能,尝试将异步操作简化为同步操作,或者确保所有异步操作都正确管理其状态和错误。
  5. 查阅 HarmonyOS 文档和社区

    • 查阅 HarmonyOS 的官方文档,了解有关 taskPool 和多线程编程的最佳实践和限制。
    • 搜索或询问 HarmonyOS 社区,看看是否有其他人遇到并解决了类似的问题。
  6. 更新和补丁

    • 确保您的 HarmonyOS 和所有相关依赖项都已更新到最新版本,以利用最新的修复和改进。
1 个回答

如果在taskPool中执行的任务尝试直接访问或修改UI组件,可能会导致崩溃,因为UI组件通常只能在主线程(UI线程)上被访问或修改。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题