移动应用上架后,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执行时确实存在崩溃的风险。