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