积分6 / 贡献0

提问0答案被采纳0文章3

[经验分享] 崩溃分析Worker instance is not running, maybe worker is terminated when PostMessage

中移-zhangzhou 显示全部楼层 发表于 2024-7-4 11:18:56

移动应用上架后,agc质量大盘中出现了崩溃:

JS_ERROR

BusinessError:Worker instance is not running, maybe worker is terminated when PostMessage

堆栈可以看出是哪个worker.postMessage报错的,具体产生崩溃的地方就看不出了,需要排查产生这个ERROR的原因。

定位到错误抛出位置Worker::CommonPostMessage

##worker.cpp

napi_value Worker::CommonPostMessage(napi_env env, napi_callback_info cbinfo, bool cloneSendable)
{
    HITRACE_HELPER_METER_NAME(__PRETTY_FUNCTION__);
    size_t argc = NapiHelper::GetCallbackInfoArgc(env, cbinfo);
    if (argc < 1) {
        ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR,
            "Worker messageObject must be not null with postMessage");
        return nullptr;
    }
    napi_value* argv = new napi_value[argc];
    ObjectScope<napi_value> scope(argv, true);
    napi_value thisVar = nullptr;
    napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, nullptr);
    Worker* worker = nullptr;
    napi_unwrap(env, thisVar, reinterpret_cast<void**>(&worker));

    if (worker == nullptr || worker->IsTerminated() || worker->IsTerminating()) {
        HILOG_ERROR("worker:: worker is nullptr when PostMessage, maybe worker is terminated");
        WorkerThrowError(env, ErrorHelper::ERR_WORKER_NOT_RUNNING, "maybe worker is terminated when PostMessage");
        return nullptr;
    }
    .......

说明运行出错时状态是worker == nullptr || worker->IsTerminated() || worker->IsTerminating()

Worker::TerminateInner方法被调用时,会使worker状态变为TERMINATEING, TERMINATED

void Worker::TerminateInner()
{
    if (IsTerminated() || IsTerminating()) {
        HILOG_INFO("worker:: worker is not in running when TerminateInner");
        return;
    }
    // 1. Update State
    UpdateWorkerState(TERMINATEING);
    // 2. send null signal
    PostMessageInner(nullptr);
}

我们的业务代码中没有主动调用terminate后postMessage,所以看其它Worker::TerminateInner的调用地方:

1.js对象销毁

napi_value Worker::Constructor(napi_env env, napi_callback_info cbinfo, bool limitSign, WorkerVersion version)
{
    ......
    napi_wrap(
        env, thisVar, worker,
        [](napi_env env, void* data, void* hint) {
            Worker* worker = reinterpret_cast<Worker*>(data);
            {
                std::lock_guard<std::recursive_mutex> lock(worker->liveStatusLock_);
                if (worker->UpdateHostState(INACTIVE)) {
#if defined(ENABLE_WORKER_EVENTHANDLER)
                    if (!worker->isMainThreadWorker_) {
                        worker->CloseHostHandle();
                    }
#else
                    worker->CloseHostHandle();
#endif
                    worker->ReleaseHostThreadContent();
                }
                if (!worker->IsRunning()) {
                    HILOG_DEBUG("worker:: worker is not in running");
                    return;
                }
                worker->TerminateInner();
            }
        },
        nullptr, &worker->workerRef_);
    worker->StartExecuteInThread(env, script);
    return thisVar;
}

2.出现异常

void Worker::HandleException()
{
    if (!NapiHelper::IsExceptionPending(workerEnv_)) {
        return;
    }

    napi_status status = napi_ok;
    HandleScope scope(workerEnv_, status);
    NAPI_CALL_RETURN_VOID(workerEnv_, status);
    napi_value exception;
    napi_get_and_clear_last_exception(workerEnv_, &exception);
    if (exception == nullptr) {
        return;
    }

    HandleUncaughtException(exception);
}
void Worker::HandleUncaughtException(napi_value exception)
{
    napi_value obj = ErrorHelper::TranslateErrorEvent(workerEnv_, exception);

    // WorkerGlobalScope onerror
    WorkerOnErrorInner(obj);

    if (hostEnv_ == nullptr) {
        HILOG_ERROR("worker:: host engine is nullptr.");
        return;
    }
    MessageDataType data = nullptr;
    napi_value undefined = NapiHelper::GetUndefinedValue(workerEnv_);
    napi_serialize_inner(workerEnv_, obj, undefined, undefined, false, true, &data);
    {
        std::lock_guard<std::recursive_mutex> lock(liveStatusLock_);
        if (HostIsStop()) {
            return;
        }
        errorQueue_.EnQueue(data);
#if defined(ENABLE_WORKER_EVENTHANDLER)
        if (isMainThreadWorker_) {
            auto hostOnErrorTask = [this]() {
                this->HostOnErrorInner();
                this->TerminateInner();
            };
            g_mainThreadHandler_->PostTask(hostOnErrorTask, "WorkerHostOnErrorTask",
                0, OHOS::AppExecFwk::EventQueue::Priority::HIGH);
        } else {
            uv_async_send(hostOnErrorSignal_);
        }
#else
        uv_async_send(hostOnErrorSignal_);
#endif
    }
}
void Worker::InitHostHandle(uv_loop_t* loop)
{
    ......
    hostOnErrorSignal_ = new uv_async_t;
    uv_async_init(loop, hostOnErrorSignal_, reinterpret_cast<uv_async_cb>(Worker::HostOnError));
    hostOnErrorSignal_->data = this;
    ......
}
void Worker::HostOnError(const uv_async_t* req)
{
    Worker* worker = static_cast<Worker*>(req->data);
    if (worker == nullptr) {
        HILOG_ERROR("worker:: worker is null");
        return;
    }
    worker->HostOnErrorInner();
    worker->TerminateInner();
}

HandleException调用的调用方:1)napi_run_actor执行worker线程文件;2)调用CallWorkerFunction,napi_call_function执行ts中的onmessage、onmessageerror或onclose方法时出错;3)宿主线程napi_call_function执行ts中message、messageerror或error。

所以,最有可能导致postMessage报错Worker instance is not running, maybe worker is terminated when PostMessage,还是宿主或worker执行ts中消息时产生异常。

回到我们自己的业务代码排查,worker文件中workerPort.onmessage执行时确实存在崩溃的风险。

©著作权归作者所有,转载或内容合作请联系作者

您尚未登录,无法参与评论,登录后可以:
参与开源共建问题交流
认同或收藏高质量问答
获取积分成为开源共建先驱

Copyright   ©2023  OpenHarmony开发者论坛  京ICP备2020036654号-3 |技术支持 Discuz!

返回顶部