HarmonyOS taskpool使用crash

堆栈如下 看堆栈式taskpool线程crash了。 这种如何定位问题呢?

Pid:9634 
Uid:20020054 
Process name:com.dewu.hos 
Reason:Signal:SIGABRT(SI_TKILL)@0x01317b56000025a2 from:9634:20020054 
Fault thread Info: 
Tid:9743, Name:OS_TaskWorker 
#00 pc 0000000000185ca8 /system/lib/ld-musl-aarch64.so.1(raise+188)(74fbb7c9c36exxxx5599de859b56a0) 
#01 pc 00000000001381a8 /system/lib/ld-musl-aarch64.so.1(abort+20)(74fbb7c9c36exxxx599de859b56a0) 
#02 pc 00000000000169c8 /system/lib64/platformsdk/libuv.so(uv__io_poll+336)(c19937065xxxx8eb4ba31207ed1a50) 
#03 pc 0000000000017728 /system/lib64/platformsdk/libuv.so(uv_run+376)(c199370656xxxxxb4ba31207ed1a50) 
#04 pc 000000000001c164 /system/lib64/module/libtaskpool.z.so(Commonlibrary::Concurrent::TaskPoolModule::Worker::ExecuteInThread(void const*)+376)(ece64a54f6fa3xxxxxx29589068cfa) 
#05 pc 0000000000019b54 /system/lib64/module/libtaskpool.z.so(Commonlibrary::Concurrent::TaskPoolModule::TaskRunner::TaskInnerRunner::Run()+68)(ece64a54f6fa3xxxxx4429589068cfa) 
#06 pc 00000000001a7e58 /system/lib/ld-musl-aarch64.so.1(start+236)(74fbb7c9c3xxxx9de859b56a0) 
#07 pc 000000000009df38 /system/lib/ld-musl-aarch64.so.1(74fbb7c9c3xxxxx599de859b56a0) 
Registers: 
x0:0000000000000000 x1:0000000829f83630 x2:0000000000000000 x3:0000000000000008 
x4:0000000829f83750 x5:0000000000000004 x6:fefeff6b60757164 x7:7f7f7f7f7f7f7f7f 
x8:0000000000000087 x9:0000000829f879d0 x10:0000000000000072 x11:0000000082355555 
x12:00000004a1ebc07c x13:000000001e52dfb7 x14:0000000015b1b174 x15:6a38a314050c0d97 
x16:00000006cc4ab078 x17:000000010be8e194 x18:0000000000000003 x19:0000000000000000 
x20:000000010c144000 x21:00000008266338c8 x22:0000000000000003 x23:00000008266336c8 
x24:0000000826633820 x25:00000000fffffffd x26:0000000000000005 x27:0000000829f87860 
x28:00000006cc48aa68 x29:0000000829f836b0 
lr:000000010be8e1ac sp:0000000829f83630 pc:000000010bedbca8
HarmonyOS
2024-08-26 17:47:54
浏览
收藏 0
回答 2
待解决
回答 2
按赞同
/
按时间
鱼弦CTO
1

在 HarmonyOS 中,taskpool 线程崩溃通常是由于某个任务或并发操作出现问题所引起的。要定位和解决这个问题,可以按照以下步骤进行分析:

### 1. 分析崩溃堆栈

根据你的堆栈信息,关键部分如下:

#00 pc 0000000000185ca8 /system/lib/ld-musl-aarch64.so.1(raise+188)
#01 pc 00000000001381a8 /system/lib/ld-musl-aarch64.so.1(abort+20)
#02 pc 00000000000169c8 /system/lib64/platformsdk/libuv.so(uv__io_poll+336)
#03 pc 0000000000017728 /system/lib64/platformsdk/libuv.so(uv_run+376)
#04 pc 000000000001c164 /system/lib64/module/libtaskpool.z.so(Commonlibrary::Concurrent::TaskPoolModule::Worker::ExecuteInThread(void const*)+376)
#05 pc 0000000000019b54 /system/lib64/module/libtaskpool.z.so(Commonlibrary::Concurrent::TaskPoolModule::TaskRunner::TaskInnerRunner::Run()+68)

从堆栈可以看到 ​​libuv​​ 库中的 ​​uv__io_poll​​ 和 ​​uv_run​​ 函数参与了事件循环,然后调用了 ​​libtaskpool.z.so​​ 库中的 ​​ExecuteInThread​​ 和 ​​TaskInnerRunner::Run​​ 函数。

### 2. 检查代码中的异步任务和线程

确保在使用 taskpool 时,每个任务的执行不会产生未捕获的异常。如果任务抛出异常且没有正确捕获处理,这可能导致线程终止。

### 3. 增加日志和错误处理

在代码中增加日志记录和错误处理,以便能更详细地了解任务执行过程中的状态和潜在问题。确保在每个任务中捕获所有可能的异常,并进行适当的处理。

#include <iostream>
#include <stdexcept>

void SafeTask() {
    try {
        // 任务逻辑
        // ...

        throw std::runtime_error("Something went wrong");
    } catch (const std::exception& e) {
        std::cerr << "Caught exception: " << e.what() << std::endl;
        // 处理异常
    }
}

### 4. 使用调试工具

使用 HarmonyOS 提供的调试工具来监控任务池和线程的状态。你可以通过调试器设置断点,逐步检查线程的执行情况。

### 5. 查看相关代码片段

重点检查 ​​Commonlibrary::Concurrent::TaskPoolModule::Worker::ExecuteInThread​​ 和 ​​Commonlibrary::Concurrent::TaskPoolModule::TaskRunner::TaskInnerRunner::Run​​ 的实现,确保这些方法内部的任务管理和线程调度逻辑没有问题。

### 6. 检查资源竞争和死锁

确保多线程环境下没有资源竞争和死锁问题。可以使用工具(如 Mutex 和 Semaphore)来保证线程安全,并避免多个线程同时访问共享资源时发生冲突。

### 示例代码:如何创建一个安全的 TaskPool

为了说明如何创建一个更安全的 TaskPool,下面是一个简化的示例代码:

#include <iostream>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <functional>

class SafeTaskPool {
public:
    SafeTaskPool(size_t numThreads);
    ~SafeTaskPool();

    void EnqueueTask(std::function<void()> task);

private:
    void WorkerThread();

    std::vector<std::thread> workers_;
    std::queue<std::function<void()>> tasks_;
    std::mutex mutex_;
    std::condition_variable condition_;
    bool stop_;
};

SafeTaskPool::SafeTaskPool(size_t numThreads) : stop_(false) {
    for (size_t i = 0; i < numThreads; ++i) {
        workers_.emplace_back(&SafeTaskPool::WorkerThread, this);
    }
}

SafeTaskPool::~SafeTaskPool() {
    {
        std::unique_lock<std::mutex> lock(mutex_);
        stop_ = true;
    }
    condition_.notify_all();
    for (std::thread& worker : workers_) {
        worker.join();
    }
}

void SafeTaskPool::EnqueueTask(std::function<void()> task) {
    {
        std::unique_lock<std::mutex> lock(mutex_);
        tasks_.push(std::move(task));
    }
    condition_.notify_one();
}

void SafeTaskPool::WorkerThread() {
    while (true) {
        std::function<void()> task;
        {
            std::unique_lock<std::mutex> lock(mutex_);
            condition_.wait(lock, [this] { return stop_ || !tasks_.empty(); });

            if (stop_ && tasks_.empty()) {
                return;
            }

            task = std::move(tasks_.front());
            tasks_.pop();
        }
        try {
            task();
        } catch (const std::exception& e) {
            std::cerr << "Task threw an exception: " << e.what() << std::endl;
        } catch (...) {
            std::cerr << "Task threw an unknown exception" << std::endl;
        }
    }
}

// 使用示例
int main() {
    SafeTaskPool pool(4);

    pool.EnqueueTask([] {
        std::cout << "Task 1" << std::endl;
    });

    pool.EnqueueTask([] {
        std::cout << "Task 2" << std::endl;
        throw std::runtime_error("Error in Task 2");
    });

    pool.EnqueueTask([] {
        std::cout << "Task 3" << std::endl;
    });

    std::this_thread::sleep_for(std::chrono::seconds(2));

    return 0;
}

### 总结

通过分析崩溃堆栈,检查代码中的异步任务和线程,增加日志和错误处理,使用调试工具,以及检查看是否存在资源竞争和死锁,你可以逐步定位和解决 taskpool 线程崩溃的问题。在多线程编程中,确保每个任务的安全性并妥善处理异常是非常重要的。希望这些建议对你有所帮助。

分享
微博
QQ
微信
回复
2024-08-26 17:54:08
superinsect

请参照这个文档排查是哪两个线程共用了:https://developer.huawei.com/consumer/cn/blog/topic/03137170307084079

SIGABRT(SI_TKILL)是进程主动中断,看堆栈是调用了标准函数库的abort()函数。这些是很典型的taskpool/worker的多线程问题。https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/bpta-cppcrash-guidance-0000001890652421-V5#section7286183943719

分享
微博
QQ
微信
回复
2024-08-26 22:43:46
相关问题
HarmonyOS TaskPool使用首选项报错
133浏览 • 1回复 待解决
HarmonyOS 遇到JSON.stringify crash
191浏览 • 1回复 待解决
如何使用taskpool实现多线程
732浏览 • 1回复 待解决
taskpool使用 ,谁有好的方案?
422浏览 • 1回复 待解决
如何实现crash堆栈抓取、crash回调
1531浏览 • 1回复 待解决
taskpool 使用问题,有人知道吗?
629浏览 • 1回复 待解决
HarmonyOS crash日志如何定位问题代码
111浏览 • 1回复 待解决
TaskPool里面是否可以使用EventHub
1539浏览 • 1回复 待解决
HarmonyOS taskpool线程数量控制
160浏览 • 2回复 待解决
HarmonyOS有防CPP crash的具体方案吗
125浏览 • 1回复 待解决
HarmonyOS taskpool数据传输问题
127浏览 • 1回复 待解决
尝试获取Har context,app crash
1523浏览 • 1回复 待解决
DFX-crash定位定界工具
396浏览 • 1回复 待解决