169570cc8Sopenharmony_ci/* 269570cc8Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 369570cc8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 469570cc8Sopenharmony_ci * you may not use this file except in compliance with the License. 569570cc8Sopenharmony_ci * You may obtain a copy of the License at 669570cc8Sopenharmony_ci * 769570cc8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 869570cc8Sopenharmony_ci * 969570cc8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1069570cc8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1169570cc8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1269570cc8Sopenharmony_ci * See the License for the specific language governing permissions and 1369570cc8Sopenharmony_ci * limitations under the License. 1469570cc8Sopenharmony_ci */ 1569570cc8Sopenharmony_ci 1669570cc8Sopenharmony_ci#include <fcntl.h> 1769570cc8Sopenharmony_ci#include <limits.h> 1869570cc8Sopenharmony_ci#include <sched.h> 1969570cc8Sopenharmony_ci#include <stdlib.h> 2069570cc8Sopenharmony_ci#include <unistd.h> 2169570cc8Sopenharmony_ci 2269570cc8Sopenharmony_ci#include <sys/ipc.h> 2369570cc8Sopenharmony_ci#include <sys/mman.h> 2469570cc8Sopenharmony_ci#include <sys/mount.h> 2569570cc8Sopenharmony_ci#include <sys/signalfd.h> 2669570cc8Sopenharmony_ci#include <sys/socket.h> 2769570cc8Sopenharmony_ci#include <sys/stat.h> 2869570cc8Sopenharmony_ci#include <sys/wait.h> 2969570cc8Sopenharmony_ci 3069570cc8Sopenharmony_ci#include "appspawn_adapter.h" 3169570cc8Sopenharmony_ci#include "appspawn_hook.h" 3269570cc8Sopenharmony_ci#include "appspawn_msg.h" 3369570cc8Sopenharmony_ci#include "appspawn_manager.h" 3469570cc8Sopenharmony_ci#include "securec.h" 3569570cc8Sopenharmony_ci 3669570cc8Sopenharmony_ci#define SLEEP_DURATION 3000 // us 3769570cc8Sopenharmony_ci#define EXIT_APP_TIMEOUT 1000000 // us 3869570cc8Sopenharmony_ci 3969570cc8Sopenharmony_cistatic AppSpawnMgr *g_appSpawnMgr = NULL; 4069570cc8Sopenharmony_ci 4169570cc8Sopenharmony_ciAppSpawnMgr *CreateAppSpawnMgr(int mode) 4269570cc8Sopenharmony_ci{ 4369570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(mode < MODE_INVALID, return NULL); 4469570cc8Sopenharmony_ci if (g_appSpawnMgr != NULL) { 4569570cc8Sopenharmony_ci return g_appSpawnMgr; 4669570cc8Sopenharmony_ci } 4769570cc8Sopenharmony_ci AppSpawnMgr *appMgr = (AppSpawnMgr *)calloc(1, sizeof(AppSpawnMgr)); 4869570cc8Sopenharmony_ci APPSPAWN_CHECK(appMgr != NULL, return NULL, "Failed to alloc memory for appspawn"); 4969570cc8Sopenharmony_ci appMgr->content.longProcName = NULL; 5069570cc8Sopenharmony_ci appMgr->content.longProcNameLen = 0; 5169570cc8Sopenharmony_ci appMgr->content.mode = mode; 5269570cc8Sopenharmony_ci appMgr->content.sandboxNsFlags = 0; 5369570cc8Sopenharmony_ci appMgr->content.wdgOpened = 0; 5469570cc8Sopenharmony_ci appMgr->servicePid = getpid(); 5569570cc8Sopenharmony_ci appMgr->server = NULL; 5669570cc8Sopenharmony_ci appMgr->sigHandler = NULL; 5769570cc8Sopenharmony_ci OH_ListInit(&appMgr->appQueue); 5869570cc8Sopenharmony_ci OH_ListInit(&appMgr->diedQueue); 5969570cc8Sopenharmony_ci OH_ListInit(&appMgr->appSpawnQueue); 6069570cc8Sopenharmony_ci appMgr->diedAppCount = 0; 6169570cc8Sopenharmony_ci OH_ListInit(&appMgr->extData); 6269570cc8Sopenharmony_ci g_appSpawnMgr = appMgr; 6369570cc8Sopenharmony_ci g_appSpawnMgr->spawnTime.minAppspawnTime = APPSPAWN_MAX_TIME; 6469570cc8Sopenharmony_ci g_appSpawnMgr->spawnTime.maxAppspawnTime = 0; 6569570cc8Sopenharmony_ci return appMgr; 6669570cc8Sopenharmony_ci} 6769570cc8Sopenharmony_ci 6869570cc8Sopenharmony_ciAppSpawnMgr *GetAppSpawnMgr(void) 6969570cc8Sopenharmony_ci{ 7069570cc8Sopenharmony_ci return g_appSpawnMgr; 7169570cc8Sopenharmony_ci} 7269570cc8Sopenharmony_ci 7369570cc8Sopenharmony_ciAppSpawnContent *GetAppSpawnContent(void) 7469570cc8Sopenharmony_ci{ 7569570cc8Sopenharmony_ci return g_appSpawnMgr == NULL ? NULL : &g_appSpawnMgr->content; 7669570cc8Sopenharmony_ci} 7769570cc8Sopenharmony_ci 7869570cc8Sopenharmony_cistatic void SpawningQueueDestroy(ListNode *node) 7969570cc8Sopenharmony_ci{ 8069570cc8Sopenharmony_ci AppSpawningCtx *property = ListEntry(node, AppSpawningCtx, node); 8169570cc8Sopenharmony_ci DeleteAppSpawningCtx(property); 8269570cc8Sopenharmony_ci} 8369570cc8Sopenharmony_ci 8469570cc8Sopenharmony_cistatic void ExtDataDestroy(ListNode *node) 8569570cc8Sopenharmony_ci{ 8669570cc8Sopenharmony_ci AppSpawnExtData *extData = ListEntry(node, AppSpawnExtData, node); 8769570cc8Sopenharmony_ci AppSpawnExtDataFree freeNode = extData->freeNode; 8869570cc8Sopenharmony_ci if (freeNode) { 8969570cc8Sopenharmony_ci freeNode(extData); 9069570cc8Sopenharmony_ci } 9169570cc8Sopenharmony_ci} 9269570cc8Sopenharmony_ci 9369570cc8Sopenharmony_civoid DeleteAppSpawnMgr(AppSpawnMgr *mgr) 9469570cc8Sopenharmony_ci{ 9569570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(mgr != NULL, return); 9669570cc8Sopenharmony_ci OH_ListRemoveAll(&mgr->appQueue, NULL); 9769570cc8Sopenharmony_ci OH_ListRemoveAll(&mgr->diedQueue, NULL); 9869570cc8Sopenharmony_ci OH_ListRemoveAll(&mgr->appSpawnQueue, SpawningQueueDestroy); 9969570cc8Sopenharmony_ci OH_ListRemoveAll(&mgr->extData, ExtDataDestroy); 10069570cc8Sopenharmony_ci 10169570cc8Sopenharmony_ci APPSPAWN_LOGV("DeleteAppSpawnMgr %{public}d %{public}d", mgr->servicePid, getpid()); 10269570cc8Sopenharmony_ci free(mgr); 10369570cc8Sopenharmony_ci if (g_appSpawnMgr == mgr) { 10469570cc8Sopenharmony_ci g_appSpawnMgr = NULL; 10569570cc8Sopenharmony_ci } 10669570cc8Sopenharmony_ci} 10769570cc8Sopenharmony_ci 10869570cc8Sopenharmony_civoid TraversalSpawnedProcess(AppTraversal traversal, void *data) 10969570cc8Sopenharmony_ci{ 11069570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(g_appSpawnMgr != NULL && traversal != NULL, return); 11169570cc8Sopenharmony_ci ListNode *node = g_appSpawnMgr->appQueue.next; 11269570cc8Sopenharmony_ci while (node != &g_appSpawnMgr->appQueue) { 11369570cc8Sopenharmony_ci ListNode *next = node->next; 11469570cc8Sopenharmony_ci AppSpawnedProcess *appInfo = ListEntry(node, AppSpawnedProcess, node); 11569570cc8Sopenharmony_ci traversal(g_appSpawnMgr, appInfo, data); 11669570cc8Sopenharmony_ci node = next; 11769570cc8Sopenharmony_ci } 11869570cc8Sopenharmony_ci} 11969570cc8Sopenharmony_ci 12069570cc8Sopenharmony_cistatic int AppInfoPidComparePro(ListNode *node, void *data) 12169570cc8Sopenharmony_ci{ 12269570cc8Sopenharmony_ci AppSpawnedProcess *node1 = ListEntry(node, AppSpawnedProcess, node); 12369570cc8Sopenharmony_ci pid_t pid = *(pid_t *)data; 12469570cc8Sopenharmony_ci return node1->pid - pid; 12569570cc8Sopenharmony_ci} 12669570cc8Sopenharmony_ci 12769570cc8Sopenharmony_cistatic int AppInfoNameComparePro(ListNode *node, void *data) 12869570cc8Sopenharmony_ci{ 12969570cc8Sopenharmony_ci AppSpawnedProcess *node1 = ListEntry(node, AppSpawnedProcess, node); 13069570cc8Sopenharmony_ci return strcmp(node1->name, (char *)data); 13169570cc8Sopenharmony_ci} 13269570cc8Sopenharmony_ci 13369570cc8Sopenharmony_cistatic int AppInfoCompareProc(ListNode *node, ListNode *newNode) 13469570cc8Sopenharmony_ci{ 13569570cc8Sopenharmony_ci AppSpawnedProcess *node1 = ListEntry(node, AppSpawnedProcess, node); 13669570cc8Sopenharmony_ci AppSpawnedProcess *node2 = ListEntry(newNode, AppSpawnedProcess, node); 13769570cc8Sopenharmony_ci return node1->pid - node2->pid; 13869570cc8Sopenharmony_ci} 13969570cc8Sopenharmony_ci 14069570cc8Sopenharmony_ciAppSpawnedProcess *AddSpawnedProcess(pid_t pid, const char *processName, bool isDebuggable) 14169570cc8Sopenharmony_ci{ 14269570cc8Sopenharmony_ci APPSPAWN_CHECK(g_appSpawnMgr != NULL && processName != NULL, return NULL, "Invalid mgr or process name"); 14369570cc8Sopenharmony_ci APPSPAWN_CHECK(pid > 0, return NULL, "Invalid pid for %{public}s", processName); 14469570cc8Sopenharmony_ci size_t len = strlen(processName) + 1; 14569570cc8Sopenharmony_ci APPSPAWN_CHECK(len > 1, return NULL, "Invalid processName for %{public}s", processName); 14669570cc8Sopenharmony_ci AppSpawnedProcess *node = (AppSpawnedProcess *)calloc(1, sizeof(AppSpawnedProcess) + len + 1); 14769570cc8Sopenharmony_ci APPSPAWN_CHECK(node != NULL, return NULL, "Failed to malloc for appinfo"); 14869570cc8Sopenharmony_ci 14969570cc8Sopenharmony_ci node->pid = pid; 15069570cc8Sopenharmony_ci node->max = 0; 15169570cc8Sopenharmony_ci node->uid = 0; 15269570cc8Sopenharmony_ci node->exitStatus = 0; 15369570cc8Sopenharmony_ci node->isDebuggable = isDebuggable; 15469570cc8Sopenharmony_ci int ret = strcpy_s(node->name, len, processName); 15569570cc8Sopenharmony_ci APPSPAWN_CHECK(ret == 0, free(node); 15669570cc8Sopenharmony_ci return NULL, "Failed to strcpy process name"); 15769570cc8Sopenharmony_ci 15869570cc8Sopenharmony_ci OH_ListInit(&node->node); 15969570cc8Sopenharmony_ci APPSPAWN_LOGI("Add %{public}s, pid=%{public}d success", processName, pid); 16069570cc8Sopenharmony_ci OH_ListAddWithOrder(&g_appSpawnMgr->appQueue, &node->node, AppInfoCompareProc); 16169570cc8Sopenharmony_ci return node; 16269570cc8Sopenharmony_ci} 16369570cc8Sopenharmony_ci 16469570cc8Sopenharmony_civoid TerminateSpawnedProcess(AppSpawnedProcess *node) 16569570cc8Sopenharmony_ci{ 16669570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(g_appSpawnMgr != NULL && node != NULL, return); 16769570cc8Sopenharmony_ci // delete node 16869570cc8Sopenharmony_ci OH_ListRemove(&node->node); 16969570cc8Sopenharmony_ci OH_ListInit(&node->node); 17069570cc8Sopenharmony_ci if (!IsNWebSpawnMode(g_appSpawnMgr)) { 17169570cc8Sopenharmony_ci free(node); 17269570cc8Sopenharmony_ci return; 17369570cc8Sopenharmony_ci } 17469570cc8Sopenharmony_ci if (g_appSpawnMgr->diedAppCount >= MAX_DIED_PROCESS_COUNT) { 17569570cc8Sopenharmony_ci AppSpawnedProcess *oldApp = ListEntry(g_appSpawnMgr->diedQueue.next, AppSpawnedProcess, node); 17669570cc8Sopenharmony_ci OH_ListRemove(&oldApp->node); 17769570cc8Sopenharmony_ci OH_ListInit(&oldApp->node); 17869570cc8Sopenharmony_ci free(oldApp); 17969570cc8Sopenharmony_ci g_appSpawnMgr->diedAppCount--; 18069570cc8Sopenharmony_ci } 18169570cc8Sopenharmony_ci APPSPAWN_LOGI("ProcessAppDied %{public}s, pid=%{public}d", node->name, node->pid); 18269570cc8Sopenharmony_ci OH_ListAddTail(&g_appSpawnMgr->diedQueue, &node->node); 18369570cc8Sopenharmony_ci g_appSpawnMgr->diedAppCount++; 18469570cc8Sopenharmony_ci} 18569570cc8Sopenharmony_ci 18669570cc8Sopenharmony_ciAppSpawnedProcess *GetSpawnedProcess(pid_t pid) 18769570cc8Sopenharmony_ci{ 18869570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(g_appSpawnMgr != NULL, return NULL); 18969570cc8Sopenharmony_ci ListNode *node = OH_ListFind(&g_appSpawnMgr->appQueue, &pid, AppInfoPidComparePro); 19069570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return NULL); 19169570cc8Sopenharmony_ci return ListEntry(node, AppSpawnedProcess, node); 19269570cc8Sopenharmony_ci} 19369570cc8Sopenharmony_ci 19469570cc8Sopenharmony_ciAppSpawnedProcess *GetSpawnedProcessByName(const char *name) 19569570cc8Sopenharmony_ci{ 19669570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(g_appSpawnMgr != NULL, return NULL); 19769570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(name != NULL, return NULL); 19869570cc8Sopenharmony_ci 19969570cc8Sopenharmony_ci ListNode *node = OH_ListFind(&g_appSpawnMgr->appQueue, (void *)name, AppInfoNameComparePro); 20069570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return NULL); 20169570cc8Sopenharmony_ci return ListEntry(node, AppSpawnedProcess, node); 20269570cc8Sopenharmony_ci} 20369570cc8Sopenharmony_ci 20469570cc8Sopenharmony_cistatic void DumpProcessSpawnStack(pid_t pid) 20569570cc8Sopenharmony_ci{ 20669570cc8Sopenharmony_ci#if (!defined(CJAPP_SPAWN) && !defined(NATIVE_SPAWN)) 20769570cc8Sopenharmony_ci DumpSpawnStack(pid); 20869570cc8Sopenharmony_ci DumpSpawnStack(getpid()); 20969570cc8Sopenharmony_ci#endif 21069570cc8Sopenharmony_ci#ifndef APPSPAWN_TEST 21169570cc8Sopenharmony_ci kill(pid, SIGKILL); 21269570cc8Sopenharmony_ci#endif 21369570cc8Sopenharmony_ci APPSPAWN_LOGI("Dump stack finished"); 21469570cc8Sopenharmony_ci} 21569570cc8Sopenharmony_ci 21669570cc8Sopenharmony_ciint KillAndWaitStatus(pid_t pid, int sig, int *exitStatus) 21769570cc8Sopenharmony_ci{ 21869570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(exitStatus != NULL, return 0); 21969570cc8Sopenharmony_ci *exitStatus = -1; 22069570cc8Sopenharmony_ci if (pid <= 0) { 22169570cc8Sopenharmony_ci return 0; 22269570cc8Sopenharmony_ci } 22369570cc8Sopenharmony_ci 22469570cc8Sopenharmony_ci if (kill(pid, sig) != 0) { 22569570cc8Sopenharmony_ci APPSPAWN_LOGE("unable to kill process, pid: %{public}d ret %{public}d", pid, errno); 22669570cc8Sopenharmony_ci return -1; 22769570cc8Sopenharmony_ci } 22869570cc8Sopenharmony_ci pid_t exitPid = 0; 22969570cc8Sopenharmony_ci int retry = 0; 23069570cc8Sopenharmony_ci while (retry * SLEEP_DURATION < EXIT_APP_TIMEOUT) { 23169570cc8Sopenharmony_ci exitPid = waitpid(pid, exitStatus, WNOHANG); 23269570cc8Sopenharmony_ci if (exitPid == pid) { 23369570cc8Sopenharmony_ci return 0; 23469570cc8Sopenharmony_ci } 23569570cc8Sopenharmony_ci usleep(SLEEP_DURATION); 23669570cc8Sopenharmony_ci retry++; 23769570cc8Sopenharmony_ci } 23869570cc8Sopenharmony_ci 23969570cc8Sopenharmony_ci DumpProcessSpawnStack(pid); 24069570cc8Sopenharmony_ci APPSPAWN_LOGE("waitpid failed, pid: %{public}d %{public}d, status: %{public}d", exitPid, pid, *exitStatus); 24169570cc8Sopenharmony_ci 24269570cc8Sopenharmony_ci return -1; 24369570cc8Sopenharmony_ci} 24469570cc8Sopenharmony_ci 24569570cc8Sopenharmony_cistatic int GetProcessTerminationStatus(pid_t pid) 24669570cc8Sopenharmony_ci{ 24769570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(g_appSpawnMgr != NULL, return -1); 24869570cc8Sopenharmony_ci APPSPAWN_LOGV("GetProcessTerminationStatus pid: %{public}d ", pid); 24969570cc8Sopenharmony_ci if (pid <= 0) { 25069570cc8Sopenharmony_ci return 0; 25169570cc8Sopenharmony_ci } 25269570cc8Sopenharmony_ci int exitStatus = 0; 25369570cc8Sopenharmony_ci ListNode *node = OH_ListFind(&g_appSpawnMgr->diedQueue, &pid, AppInfoPidComparePro); 25469570cc8Sopenharmony_ci if (node != NULL) { 25569570cc8Sopenharmony_ci AppSpawnedProcess *info = ListEntry(node, AppSpawnedProcess, node); 25669570cc8Sopenharmony_ci exitStatus = info->exitStatus; 25769570cc8Sopenharmony_ci OH_ListRemove(node); 25869570cc8Sopenharmony_ci OH_ListInit(node); 25969570cc8Sopenharmony_ci free(info); 26069570cc8Sopenharmony_ci if (g_appSpawnMgr->diedAppCount > 0) { 26169570cc8Sopenharmony_ci g_appSpawnMgr->diedAppCount--; 26269570cc8Sopenharmony_ci } 26369570cc8Sopenharmony_ci return exitStatus; 26469570cc8Sopenharmony_ci } 26569570cc8Sopenharmony_ci AppSpawnedProcess *app = GetSpawnedProcess(pid); 26669570cc8Sopenharmony_ci if (app == NULL) { 26769570cc8Sopenharmony_ci APPSPAWN_LOGE("unable to get process, pid: %{public}d ", pid); 26869570cc8Sopenharmony_ci return -1; 26969570cc8Sopenharmony_ci } 27069570cc8Sopenharmony_ci 27169570cc8Sopenharmony_ci if (KillAndWaitStatus(pid, SIGKILL, &exitStatus) == 0) { // kill success, delete app 27269570cc8Sopenharmony_ci OH_ListRemove(&app->node); 27369570cc8Sopenharmony_ci OH_ListInit(&app->node); 27469570cc8Sopenharmony_ci free(app); 27569570cc8Sopenharmony_ci } 27669570cc8Sopenharmony_ci return exitStatus; 27769570cc8Sopenharmony_ci} 27869570cc8Sopenharmony_ci 27969570cc8Sopenharmony_ciAppSpawningCtx *CreateAppSpawningCtx(void) 28069570cc8Sopenharmony_ci{ 28169570cc8Sopenharmony_ci static uint32_t requestId = 0; 28269570cc8Sopenharmony_ci AppSpawningCtx *property = (AppSpawningCtx *)malloc(sizeof(AppSpawningCtx)); 28369570cc8Sopenharmony_ci APPSPAWN_CHECK(property != NULL, return NULL, "Failed to create AppSpawningCtx "); 28469570cc8Sopenharmony_ci property->client.id = ++requestId; 28569570cc8Sopenharmony_ci property->client.flags = 0; 28669570cc8Sopenharmony_ci property->forkCtx.watcherHandle = NULL; 28769570cc8Sopenharmony_ci property->forkCtx.pidFdWatcherHandle = NULL; 28869570cc8Sopenharmony_ci property->forkCtx.coldRunPath = NULL; 28969570cc8Sopenharmony_ci property->forkCtx.timer = NULL; 29069570cc8Sopenharmony_ci property->forkCtx.fd[0] = -1; 29169570cc8Sopenharmony_ci property->forkCtx.fd[1] = -1; 29269570cc8Sopenharmony_ci property->isPrefork = false; 29369570cc8Sopenharmony_ci property->forkCtx.childMsg = NULL; 29469570cc8Sopenharmony_ci property->message = NULL; 29569570cc8Sopenharmony_ci property->pid = 0; 29669570cc8Sopenharmony_ci property->state = APP_STATE_IDLE; 29769570cc8Sopenharmony_ci OH_ListInit(&property->node); 29869570cc8Sopenharmony_ci if (g_appSpawnMgr) { 29969570cc8Sopenharmony_ci OH_ListAddTail(&g_appSpawnMgr->appSpawnQueue, &property->node); 30069570cc8Sopenharmony_ci } 30169570cc8Sopenharmony_ci return property; 30269570cc8Sopenharmony_ci} 30369570cc8Sopenharmony_ci 30469570cc8Sopenharmony_civoid DeleteAppSpawningCtx(AppSpawningCtx *property) 30569570cc8Sopenharmony_ci{ 30669570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(property != NULL, return); 30769570cc8Sopenharmony_ci APPSPAWN_LOGV("DeleteAppSpawningCtx"); 30869570cc8Sopenharmony_ci 30969570cc8Sopenharmony_ci DeleteAppSpawnMsg(property->message); 31069570cc8Sopenharmony_ci 31169570cc8Sopenharmony_ci OH_ListRemove(&property->node); 31269570cc8Sopenharmony_ci if (property->forkCtx.timer) { 31369570cc8Sopenharmony_ci LE_StopTimer(LE_GetDefaultLoop(), property->forkCtx.timer); 31469570cc8Sopenharmony_ci property->forkCtx.timer = NULL; 31569570cc8Sopenharmony_ci } 31669570cc8Sopenharmony_ci if (property->forkCtx.watcherHandle) { 31769570cc8Sopenharmony_ci LE_RemoveWatcher(LE_GetDefaultLoop(), property->forkCtx.watcherHandle); 31869570cc8Sopenharmony_ci property->forkCtx.watcherHandle = NULL; 31969570cc8Sopenharmony_ci } 32069570cc8Sopenharmony_ci if (property->forkCtx.coldRunPath) { 32169570cc8Sopenharmony_ci free(property->forkCtx.coldRunPath); 32269570cc8Sopenharmony_ci property->forkCtx.coldRunPath = NULL; 32369570cc8Sopenharmony_ci } 32469570cc8Sopenharmony_ci if (property->forkCtx.fd[0] >= 0) { 32569570cc8Sopenharmony_ci close(property->forkCtx.fd[0]); 32669570cc8Sopenharmony_ci } 32769570cc8Sopenharmony_ci if (property->forkCtx.fd[1] >= 0) { 32869570cc8Sopenharmony_ci close(property->forkCtx.fd[1]); 32969570cc8Sopenharmony_ci } 33069570cc8Sopenharmony_ci 33169570cc8Sopenharmony_ci free(property); 33269570cc8Sopenharmony_ci} 33369570cc8Sopenharmony_ci 33469570cc8Sopenharmony_cistatic int AppPropertyComparePid(ListNode *node, void *data) 33569570cc8Sopenharmony_ci{ 33669570cc8Sopenharmony_ci AppSpawningCtx *property = ListEntry(node, AppSpawningCtx, node); 33769570cc8Sopenharmony_ci if (property->pid == *(pid_t *)data) { 33869570cc8Sopenharmony_ci return 0; 33969570cc8Sopenharmony_ci } 34069570cc8Sopenharmony_ci return 1; 34169570cc8Sopenharmony_ci} 34269570cc8Sopenharmony_ci 34369570cc8Sopenharmony_ciAppSpawningCtx *GetAppSpawningCtxByPid(pid_t pid) 34469570cc8Sopenharmony_ci{ 34569570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(g_appSpawnMgr != NULL, return NULL); 34669570cc8Sopenharmony_ci ListNode *node = OH_ListFind(&g_appSpawnMgr->appSpawnQueue, (void *)&pid, AppPropertyComparePid); 34769570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return NULL); 34869570cc8Sopenharmony_ci return ListEntry(node, AppSpawningCtx, node); 34969570cc8Sopenharmony_ci} 35069570cc8Sopenharmony_ci 35169570cc8Sopenharmony_civoid AppSpawningCtxTraversal(ProcessTraversal traversal, void *data) 35269570cc8Sopenharmony_ci{ 35369570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(g_appSpawnMgr != NULL && traversal != NULL, return); 35469570cc8Sopenharmony_ci ListNode *node = g_appSpawnMgr->appSpawnQueue.next; 35569570cc8Sopenharmony_ci while (node != &g_appSpawnMgr->appSpawnQueue) { 35669570cc8Sopenharmony_ci ListNode *next = node->next; 35769570cc8Sopenharmony_ci AppSpawningCtx *ctx = ListEntry(node, AppSpawningCtx, node); 35869570cc8Sopenharmony_ci traversal(g_appSpawnMgr, ctx, data); 35969570cc8Sopenharmony_ci node = next; 36069570cc8Sopenharmony_ci } 36169570cc8Sopenharmony_ci} 36269570cc8Sopenharmony_ci 36369570cc8Sopenharmony_cistatic int DumpAppSpawnQueue(ListNode *node, void *data) 36469570cc8Sopenharmony_ci{ 36569570cc8Sopenharmony_ci AppSpawningCtx *property = ListEntry(node, AppSpawningCtx, node); 36669570cc8Sopenharmony_ci APPSPAPWN_DUMP("app property id: %{public}u flags: %{public}x", 36769570cc8Sopenharmony_ci property->client.id, property->client.flags); 36869570cc8Sopenharmony_ci APPSPAPWN_DUMP("app property state: %{public}d", property->state); 36969570cc8Sopenharmony_ci 37069570cc8Sopenharmony_ci DumpAppSpawnMsg(property->message); 37169570cc8Sopenharmony_ci return 0; 37269570cc8Sopenharmony_ci} 37369570cc8Sopenharmony_ci 37469570cc8Sopenharmony_cistatic int DumpAppQueue(ListNode *node, void *data) 37569570cc8Sopenharmony_ci{ 37669570cc8Sopenharmony_ci AppSpawnedProcess *appInfo = ListEntry(node, AppSpawnedProcess, node); 37769570cc8Sopenharmony_ci uint64_t diff = DiffTime(&appInfo->spawnStart, &appInfo->spawnEnd); 37869570cc8Sopenharmony_ci APPSPAPWN_DUMP("App info uid: %{public}u pid: %{public}x", appInfo->uid, appInfo->pid); 37969570cc8Sopenharmony_ci APPSPAPWN_DUMP("App info name: %{public}s exitStatus: 0x%{public}x spawn time: %{public}" PRIu64 " us ", 38069570cc8Sopenharmony_ci appInfo->name, appInfo->exitStatus, diff); 38169570cc8Sopenharmony_ci return 0; 38269570cc8Sopenharmony_ci} 38369570cc8Sopenharmony_ci 38469570cc8Sopenharmony_cistatic int DumpExtData(ListNode *node, void *data) 38569570cc8Sopenharmony_ci{ 38669570cc8Sopenharmony_ci AppSpawnExtData *extData = ListEntry(node, AppSpawnExtData, node); 38769570cc8Sopenharmony_ci if (extData->dumpNode) { 38869570cc8Sopenharmony_ci extData->dumpNode(extData); 38969570cc8Sopenharmony_ci } 39069570cc8Sopenharmony_ci return 0; 39169570cc8Sopenharmony_ci} 39269570cc8Sopenharmony_ci 39369570cc8Sopenharmony_civoid ProcessAppSpawnDumpMsg(const AppSpawnMsgNode *message) 39469570cc8Sopenharmony_ci{ 39569570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(g_appSpawnMgr != NULL && message != NULL, return); 39669570cc8Sopenharmony_ci FILE *stream = NULL; 39769570cc8Sopenharmony_ci uint32_t len = 0; 39869570cc8Sopenharmony_ci char *ptyName = GetAppSpawnMsgExtInfo(message, "pty-name", &len); 39969570cc8Sopenharmony_ci if (ptyName != NULL) { 40069570cc8Sopenharmony_ci APPSPAWN_LOGI("Dump info to file '%{public}s'", ptyName); 40169570cc8Sopenharmony_ci char canonicalPtyPath[PATH_MAX] = {0}; 40269570cc8Sopenharmony_ci if (realpath(ptyName, canonicalPtyPath) == NULL) { 40369570cc8Sopenharmony_ci return; 40469570cc8Sopenharmony_ci } 40569570cc8Sopenharmony_ci stream = fopen(canonicalPtyPath, "w"); 40669570cc8Sopenharmony_ci SetDumpToStream(stream); 40769570cc8Sopenharmony_ci } else { 40869570cc8Sopenharmony_ci SetDumpToStream(stdout); 40969570cc8Sopenharmony_ci } 41069570cc8Sopenharmony_ci APPSPAPWN_DUMP("Dump appspawn info start ... "); 41169570cc8Sopenharmony_ci APPSPAPWN_DUMP("APP spawning queue: "); 41269570cc8Sopenharmony_ci OH_ListTraversal((ListNode *)&g_appSpawnMgr->appSpawnQueue, NULL, DumpAppSpawnQueue, 0); 41369570cc8Sopenharmony_ci APPSPAPWN_DUMP("APP queue: "); 41469570cc8Sopenharmony_ci OH_ListTraversal((ListNode *)&g_appSpawnMgr->appQueue, "App queue", DumpAppQueue, 0); 41569570cc8Sopenharmony_ci APPSPAPWN_DUMP("APP died queue: "); 41669570cc8Sopenharmony_ci OH_ListTraversal((ListNode *)&g_appSpawnMgr->diedQueue, "App died queue", DumpAppQueue, 0); 41769570cc8Sopenharmony_ci APPSPAPWN_DUMP("Ext data: "); 41869570cc8Sopenharmony_ci OH_ListTraversal((ListNode *)&g_appSpawnMgr->extData, "Ext data", DumpExtData, 0); 41969570cc8Sopenharmony_ci APPSPAPWN_DUMP("Dump appspawn info finish "); 42069570cc8Sopenharmony_ci if (stream != NULL) { 42169570cc8Sopenharmony_ci (void)fflush(stream); 42269570cc8Sopenharmony_ci fclose(stream); 42369570cc8Sopenharmony_ci#ifdef APPSPAWN_TEST 42469570cc8Sopenharmony_ci SetDumpToStream(stdout); 42569570cc8Sopenharmony_ci#else 42669570cc8Sopenharmony_ci SetDumpToStream(NULL); 42769570cc8Sopenharmony_ci#endif 42869570cc8Sopenharmony_ci } 42969570cc8Sopenharmony_ci} 43069570cc8Sopenharmony_ci 43169570cc8Sopenharmony_ciint ProcessTerminationStatusMsg(const AppSpawnMsgNode *message, AppSpawnResult *result) 43269570cc8Sopenharmony_ci{ 43369570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(g_appSpawnMgr != NULL && message != NULL, return -1); 43469570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(result != NULL, return -1); 43569570cc8Sopenharmony_ci if (!IsNWebSpawnMode(g_appSpawnMgr)) { 43669570cc8Sopenharmony_ci return APPSPAWN_MSG_INVALID; 43769570cc8Sopenharmony_ci } 43869570cc8Sopenharmony_ci result->result = -1; 43969570cc8Sopenharmony_ci result->pid = 0; 44069570cc8Sopenharmony_ci pid_t *pid = (pid_t *)GetAppSpawnMsgInfo(message, TLV_RENDER_TERMINATION_INFO); 44169570cc8Sopenharmony_ci if (pid == NULL) { 44269570cc8Sopenharmony_ci return -1; 44369570cc8Sopenharmony_ci } 44469570cc8Sopenharmony_ci // get render process termination status, only nwebspawn need this logic. 44569570cc8Sopenharmony_ci result->pid = *pid; 44669570cc8Sopenharmony_ci result->result = GetProcessTerminationStatus(*pid); 44769570cc8Sopenharmony_ci return 0; 44869570cc8Sopenharmony_ci} 449