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 "appspawn_service.h"
1769570cc8Sopenharmony_ci
1869570cc8Sopenharmony_ci#include <dirent.h>
1969570cc8Sopenharmony_ci#include <fcntl.h>
2069570cc8Sopenharmony_ci#include <stdio.h>
2169570cc8Sopenharmony_ci#include <stdlib.h>
2269570cc8Sopenharmony_ci#include <string.h>
2369570cc8Sopenharmony_ci#include <sys/signalfd.h>
2469570cc8Sopenharmony_ci#include <sys/socket.h>
2569570cc8Sopenharmony_ci#include <sys/wait.h>
2669570cc8Sopenharmony_ci#include <sys/mman.h>
2769570cc8Sopenharmony_ci#include <sys/syscall.h>
2869570cc8Sopenharmony_ci#include <signal.h>
2969570cc8Sopenharmony_ci#include <sys/mount.h>
3069570cc8Sopenharmony_ci#include <unistd.h>
3169570cc8Sopenharmony_ci#include <sys/prctl.h>
3269570cc8Sopenharmony_ci
3369570cc8Sopenharmony_ci#include "appspawn.h"
3469570cc8Sopenharmony_ci#include "appspawn_hook.h"
3569570cc8Sopenharmony_ci#include "appspawn_modulemgr.h"
3669570cc8Sopenharmony_ci#include "appspawn_manager.h"
3769570cc8Sopenharmony_ci#include "appspawn_msg.h"
3869570cc8Sopenharmony_ci#include "appspawn_server.h"
3969570cc8Sopenharmony_ci#include "appspawn_utils.h"
4069570cc8Sopenharmony_ci#include "init_socket.h"
4169570cc8Sopenharmony_ci#include "init_utils.h"
4269570cc8Sopenharmony_ci#include "parameter.h"
4369570cc8Sopenharmony_ci#include "appspawn_adapter.h"
4469570cc8Sopenharmony_ci#include "securec.h"
4569570cc8Sopenharmony_ci#include "cJSON.h"
4669570cc8Sopenharmony_ci#ifdef APPSPAWN_HISYSEVENT
4769570cc8Sopenharmony_ci#include "appspawn_hisysevent.h"
4869570cc8Sopenharmony_ci#endif
4969570cc8Sopenharmony_ci#ifdef USE_ENCAPS
5069570cc8Sopenharmony_ci#include <sys/ioctl.h>
5169570cc8Sopenharmony_ci#endif
5269570cc8Sopenharmony_ci#define PARAM_BUFFER_SIZE 10
5369570cc8Sopenharmony_ci#define PATH_SIZE 256
5469570cc8Sopenharmony_ci#define FD_PATH_SIZE 128
5569570cc8Sopenharmony_ci#define MAX_MEM_SIZE (4 * 1024)
5669570cc8Sopenharmony_ci#define APPSPAWN_MSG_USER_CHECK_COUNT 3
5769570cc8Sopenharmony_ci#define PREFORK_PROCESS "apppool"
5869570cc8Sopenharmony_ci#ifndef PIDFD_NONBLOCK
5969570cc8Sopenharmony_ci#define PIDFD_NONBLOCK O_NONBLOCK
6069570cc8Sopenharmony_ci#endif
6169570cc8Sopenharmony_ci
6269570cc8Sopenharmony_cistatic void WaitChildTimeout(const TimerHandle taskHandle, void *context);
6369570cc8Sopenharmony_cistatic void ProcessChildResponse(const WatcherHandle taskHandle, int fd, uint32_t *events, const void *context);
6469570cc8Sopenharmony_cistatic void WaitChildDied(pid_t pid);
6569570cc8Sopenharmony_cistatic void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, uint32_t buffLen);
6669570cc8Sopenharmony_cistatic void ProcessRecvMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message);
6769570cc8Sopenharmony_ci
6869570cc8Sopenharmony_ci#ifdef USE_ENCAPS
6969570cc8Sopenharmony_cistatic int OpenDevEncaps(void)
7069570cc8Sopenharmony_ci{
7169570cc8Sopenharmony_ci    int fd = open("/dev/encaps", O_RDWR);
7269570cc8Sopenharmony_ci    if (fd < 0) {
7369570cc8Sopenharmony_ci        APPSPAWN_LOGE("AppSpawnChild SetEncapsFlag open failed");
7469570cc8Sopenharmony_ci        return -1;
7569570cc8Sopenharmony_ci    }
7669570cc8Sopenharmony_ci    return fd;
7769570cc8Sopenharmony_ci}
7869570cc8Sopenharmony_ci
7969570cc8Sopenharmony_cistatic void CloseDevEncaps(int fd)
8069570cc8Sopenharmony_ci{
8169570cc8Sopenharmony_ci    if (fd < 0) {
8269570cc8Sopenharmony_ci        return;
8369570cc8Sopenharmony_ci    }
8469570cc8Sopenharmony_ci    close(fd);
8569570cc8Sopenharmony_ci}
8669570cc8Sopenharmony_ci#endif
8769570cc8Sopenharmony_ci
8869570cc8Sopenharmony_ci// FD_CLOEXEC
8969570cc8Sopenharmony_cistatic inline void SetFdCtrl(int fd, int opt)
9069570cc8Sopenharmony_ci{
9169570cc8Sopenharmony_ci    int option = fcntl(fd, F_GETFD);
9269570cc8Sopenharmony_ci    int ret = fcntl(fd, F_SETFD, (unsigned int)option | (unsigned int)opt);
9369570cc8Sopenharmony_ci    if (ret < 0) {
9469570cc8Sopenharmony_ci        APPSPAWN_LOGI("Set fd %{public}d option %{public}d %{public}d result: %{public}d", fd, option, opt, errno);
9569570cc8Sopenharmony_ci    }
9669570cc8Sopenharmony_ci}
9769570cc8Sopenharmony_ci
9869570cc8Sopenharmony_cistatic void AppQueueDestroyProc(const AppSpawnMgr *mgr, AppSpawnedProcess *appInfo, void *data)
9969570cc8Sopenharmony_ci{
10069570cc8Sopenharmony_ci    pid_t pid = appInfo->pid;
10169570cc8Sopenharmony_ci    APPSPAWN_LOGI("kill %{public}s pid: %{public}d", appInfo->name, appInfo->pid);
10269570cc8Sopenharmony_ci    // notify child proess died,clean sandbox info
10369570cc8Sopenharmony_ci    ProcessMgrHookExecute(STAGE_SERVER_APP_DIED, GetAppSpawnContent(), appInfo);
10469570cc8Sopenharmony_ci    OH_ListRemove(&appInfo->node);
10569570cc8Sopenharmony_ci    OH_ListInit(&appInfo->node);
10669570cc8Sopenharmony_ci    free(appInfo);
10769570cc8Sopenharmony_ci    if (pid > 0 && kill(pid, SIGKILL) != 0) {
10869570cc8Sopenharmony_ci        APPSPAWN_LOGE("unable to kill process, pid: %{public}d errno: %{public}d", pid, errno);
10969570cc8Sopenharmony_ci    }
11069570cc8Sopenharmony_ci}
11169570cc8Sopenharmony_ci
11269570cc8Sopenharmony_cistatic void StopAppSpawn(void)
11369570cc8Sopenharmony_ci{
11469570cc8Sopenharmony_ci    // delete nwespawn, and wait exit. Otherwise, the process of nwebspawn spawning will become zombie
11569570cc8Sopenharmony_ci    AppSpawnedProcess *appInfo = GetSpawnedProcessByName(NWEBSPAWN_SERVER_NAME);
11669570cc8Sopenharmony_ci    if (appInfo != NULL) {
11769570cc8Sopenharmony_ci        APPSPAWN_LOGI("kill %{public}s pid: %{public}d", appInfo->name, appInfo->pid);
11869570cc8Sopenharmony_ci        int exitStatus = 0;
11969570cc8Sopenharmony_ci        KillAndWaitStatus(appInfo->pid, SIGTERM, &exitStatus);
12069570cc8Sopenharmony_ci        OH_ListRemove(&appInfo->node);
12169570cc8Sopenharmony_ci        OH_ListInit(&appInfo->node);
12269570cc8Sopenharmony_ci        free(appInfo);
12369570cc8Sopenharmony_ci    }
12469570cc8Sopenharmony_ci    // delete nativespawn, and wait exit. Otherwise, the process of nativespawn spawning will become zombie
12569570cc8Sopenharmony_ci    appInfo = GetSpawnedProcessByName(NATIVESPAWN_SERVER_NAME);
12669570cc8Sopenharmony_ci    if (appInfo != NULL) {
12769570cc8Sopenharmony_ci        APPSPAWN_LOGI("kill %{public}s pid: %{public}d", appInfo->name, appInfo->pid);
12869570cc8Sopenharmony_ci        int exitStatus = 0;
12969570cc8Sopenharmony_ci        KillAndWaitStatus(appInfo->pid, SIGTERM, &exitStatus);
13069570cc8Sopenharmony_ci        OH_ListRemove(&appInfo->node);
13169570cc8Sopenharmony_ci        OH_ListInit(&appInfo->node);
13269570cc8Sopenharmony_ci        free(appInfo);
13369570cc8Sopenharmony_ci    }
13469570cc8Sopenharmony_ci    TraversalSpawnedProcess(AppQueueDestroyProc, NULL);
13569570cc8Sopenharmony_ci    APPSPAWN_LOGI("StopAppSpawn ");
13669570cc8Sopenharmony_ci#ifdef APPSPAWN_HISYSEVENT
13769570cc8Sopenharmony_ci    AppSpawnHiSysEventWrite();
13869570cc8Sopenharmony_ci#endif
13969570cc8Sopenharmony_ci    LE_StopLoop(LE_GetDefaultLoop());
14069570cc8Sopenharmony_ci}
14169570cc8Sopenharmony_ci
14269570cc8Sopenharmony_cistatic inline void DumpStatus(const char *appName, pid_t pid, int status)
14369570cc8Sopenharmony_ci{
14469570cc8Sopenharmony_ci    if (WIFSIGNALED(status)) {
14569570cc8Sopenharmony_ci        APPSPAWN_LOGW("%{public}s with pid %{public}d exit with signal:%{public}d", appName, pid, WTERMSIG(status));
14669570cc8Sopenharmony_ci    }
14769570cc8Sopenharmony_ci    if (WIFEXITED(status)) {
14869570cc8Sopenharmony_ci        APPSPAWN_LOGW("%{public}s with pid %{public}d exit with code:%{public}d", appName, pid, WEXITSTATUS(status));
14969570cc8Sopenharmony_ci    }
15069570cc8Sopenharmony_ci}
15169570cc8Sopenharmony_ci
15269570cc8Sopenharmony_cistatic void HandleDiedPid(pid_t pid, uid_t uid, int status)
15369570cc8Sopenharmony_ci{
15469570cc8Sopenharmony_ci    AppSpawnContent *content = GetAppSpawnContent();
15569570cc8Sopenharmony_ci    if (pid == content->reservedPid) {
15669570cc8Sopenharmony_ci        APPSPAWN_LOGW("HandleDiedPid with reservedPid %{public}d", pid);
15769570cc8Sopenharmony_ci        content->reservedPid = 0;
15869570cc8Sopenharmony_ci    }
15969570cc8Sopenharmony_ci    AppSpawnedProcess *appInfo = GetSpawnedProcess(pid);
16069570cc8Sopenharmony_ci    if (appInfo == NULL) { // If an exception occurs during app spawning, kill pid, return failed
16169570cc8Sopenharmony_ci        WaitChildDied(pid);
16269570cc8Sopenharmony_ci        DumpStatus("unknown", pid, status);
16369570cc8Sopenharmony_ci        return;
16469570cc8Sopenharmony_ci    }
16569570cc8Sopenharmony_ci
16669570cc8Sopenharmony_ci    appInfo->exitStatus = status;
16769570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_LOG(appInfo->uid == uid, "Invalid uid %{public}u %{public}u", appInfo->uid, uid);
16869570cc8Sopenharmony_ci    DumpStatus(appInfo->name, pid, status);
16969570cc8Sopenharmony_ci    ProcessMgrHookExecute(STAGE_SERVER_APP_DIED, GetAppSpawnContent(), appInfo);
17069570cc8Sopenharmony_ci
17169570cc8Sopenharmony_ci    // if current process of death is nwebspawn, restart appspawn
17269570cc8Sopenharmony_ci    if (strcmp(appInfo->name, NWEBSPAWN_SERVER_NAME) == 0) {
17369570cc8Sopenharmony_ci        OH_ListRemove(&appInfo->node);
17469570cc8Sopenharmony_ci        free(appInfo);
17569570cc8Sopenharmony_ci        APPSPAWN_LOGW("Current process of death is nwebspawn, pid = %{public}d, restart appspawn", pid);
17669570cc8Sopenharmony_ci        StopAppSpawn();
17769570cc8Sopenharmony_ci        return;
17869570cc8Sopenharmony_ci    }
17969570cc8Sopenharmony_ci    // move app info to died queue in NWEBSPAWN, or delete appinfo
18069570cc8Sopenharmony_ci    TerminateSpawnedProcess(appInfo);
18169570cc8Sopenharmony_ci}
18269570cc8Sopenharmony_ci
18369570cc8Sopenharmony_ciAPPSPAWN_STATIC void ProcessSignal(const struct signalfd_siginfo *siginfo)
18469570cc8Sopenharmony_ci{
18569570cc8Sopenharmony_ci    APPSPAWN_LOGI("ProcessSignal signum %{public}d %{public}d", siginfo->ssi_signo, siginfo->ssi_pid);
18669570cc8Sopenharmony_ci    switch (siginfo->ssi_signo) {
18769570cc8Sopenharmony_ci        case SIGCHLD: { // delete pid from app map
18869570cc8Sopenharmony_ci            pid_t pid;
18969570cc8Sopenharmony_ci            int status;
19069570cc8Sopenharmony_ci            while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
19169570cc8Sopenharmony_ci                APPSPAWN_CHECK(WIFSIGNALED(status) || WIFEXITED(status), return,
19269570cc8Sopenharmony_ci                    "ProcessSignal with wrong status:%{public}d", status);
19369570cc8Sopenharmony_ci                HandleDiedPid(pid, siginfo->ssi_uid, status);
19469570cc8Sopenharmony_ci            }
19569570cc8Sopenharmony_ci#if (defined(CJAPP_SPAWN) || defined(NATIVE_SPAWN))
19669570cc8Sopenharmony_ci            if (OH_ListGetCnt(&GetAppSpawnMgr()->appQueue) == 0) {
19769570cc8Sopenharmony_ci                LE_StopLoop(LE_GetDefaultLoop());
19869570cc8Sopenharmony_ci            }
19969570cc8Sopenharmony_ci#endif
20069570cc8Sopenharmony_ci            break;
20169570cc8Sopenharmony_ci        }
20269570cc8Sopenharmony_ci        case SIGTERM: { // appswapn killed, use kill without parameter
20369570cc8Sopenharmony_ci            StopAppSpawn();
20469570cc8Sopenharmony_ci            break;
20569570cc8Sopenharmony_ci        }
20669570cc8Sopenharmony_ci        default:
20769570cc8Sopenharmony_ci            APPSPAWN_LOGI("SigHandler, unsupported signal %{public}d.", siginfo->ssi_signo);
20869570cc8Sopenharmony_ci            break;
20969570cc8Sopenharmony_ci    }
21069570cc8Sopenharmony_ci}
21169570cc8Sopenharmony_ci
21269570cc8Sopenharmony_cistatic void AppSpawningCtxOnClose(const AppSpawnMgr *mgr, AppSpawningCtx *ctx, void *data)
21369570cc8Sopenharmony_ci{
21469570cc8Sopenharmony_ci    if (ctx == NULL || ctx->message == NULL || ctx->message->connection != data) {
21569570cc8Sopenharmony_ci        return;
21669570cc8Sopenharmony_ci    }
21769570cc8Sopenharmony_ci    APPSPAWN_LOGI("Kill process, pid: %{public}d app: %{public}s", ctx->pid, GetProcessName(ctx));
21869570cc8Sopenharmony_ci    if (ctx->pid > 0 && kill(ctx->pid, SIGKILL) != 0) {
21969570cc8Sopenharmony_ci        APPSPAWN_LOGE("unable to kill process, pid: %{public}d errno: %{public}d", ctx->pid, errno);
22069570cc8Sopenharmony_ci    }
22169570cc8Sopenharmony_ci    DeleteAppSpawningCtx(ctx);
22269570cc8Sopenharmony_ci}
22369570cc8Sopenharmony_ci
22469570cc8Sopenharmony_cistatic void OnClose(const TaskHandle taskHandle)
22569570cc8Sopenharmony_ci{
22669570cc8Sopenharmony_ci    if (!IsSpawnServer(GetAppSpawnMgr())) {
22769570cc8Sopenharmony_ci        return;
22869570cc8Sopenharmony_ci    }
22969570cc8Sopenharmony_ci    AppSpawnConnection *connection = (AppSpawnConnection *)LE_GetUserData(taskHandle);
23069570cc8Sopenharmony_ci    APPSPAWN_CHECK(connection != NULL, return, "Invalid connection");
23169570cc8Sopenharmony_ci    if (connection->receiverCtx.timer) {
23269570cc8Sopenharmony_ci        LE_StopTimer(LE_GetDefaultLoop(), connection->receiverCtx.timer);
23369570cc8Sopenharmony_ci        connection->receiverCtx.timer = NULL;
23469570cc8Sopenharmony_ci    }
23569570cc8Sopenharmony_ci    APPSPAWN_LOGI("OnClose connectionId: %{public}u socket %{public}d",
23669570cc8Sopenharmony_ci        connection->connectionId, LE_GetSocketFd(taskHandle));
23769570cc8Sopenharmony_ci    DeleteAppSpawnMsg(connection->receiverCtx.incompleteMsg);
23869570cc8Sopenharmony_ci    connection->receiverCtx.incompleteMsg = NULL;
23969570cc8Sopenharmony_ci    // connect close, to close spawning app
24069570cc8Sopenharmony_ci    AppSpawningCtxTraversal(AppSpawningCtxOnClose, connection);
24169570cc8Sopenharmony_ci}
24269570cc8Sopenharmony_ci
24369570cc8Sopenharmony_cistatic void OnDisConnect(const TaskHandle taskHandle)
24469570cc8Sopenharmony_ci{
24569570cc8Sopenharmony_ci    AppSpawnConnection *connection = (AppSpawnConnection *)LE_GetUserData(taskHandle);
24669570cc8Sopenharmony_ci    APPSPAWN_CHECK(connection != NULL, return, "Invalid connection");
24769570cc8Sopenharmony_ci    APPSPAWN_LOGI("OnDisConnect connectionId: %{public}u socket %{public}d",
24869570cc8Sopenharmony_ci        connection->connectionId, LE_GetSocketFd(taskHandle));
24969570cc8Sopenharmony_ci    OnClose(taskHandle);
25069570cc8Sopenharmony_ci}
25169570cc8Sopenharmony_ci
25269570cc8Sopenharmony_cistatic void SendMessageComplete(const TaskHandle taskHandle, BufferHandle handle)
25369570cc8Sopenharmony_ci{
25469570cc8Sopenharmony_ci    AppSpawnConnection *connection = (AppSpawnConnection *)LE_GetUserData(taskHandle);
25569570cc8Sopenharmony_ci    APPSPAWN_CHECK(connection != NULL, return, "Invalid connection");
25669570cc8Sopenharmony_ci    uint32_t bufferSize = sizeof(AppSpawnResponseMsg);
25769570cc8Sopenharmony_ci    AppSpawnResponseMsg *msg = (AppSpawnResponseMsg *)LE_GetBufferInfo(handle, NULL, &bufferSize);
25869570cc8Sopenharmony_ci    if (msg == NULL) {
25969570cc8Sopenharmony_ci        return;
26069570cc8Sopenharmony_ci    }
26169570cc8Sopenharmony_ci    AppSpawnedProcess *appInfo = GetSpawnedProcess(msg->result.pid);
26269570cc8Sopenharmony_ci    if (appInfo == NULL) {
26369570cc8Sopenharmony_ci        return;
26469570cc8Sopenharmony_ci    }
26569570cc8Sopenharmony_ci    APPSPAWN_LOGI("SendMessageComplete connectionId: %{public}u result %{public}d app %{public}s pid %{public}d",
26669570cc8Sopenharmony_ci        connection->connectionId, LE_GetSendResult(handle), appInfo->name, msg->result.pid);
26769570cc8Sopenharmony_ci    if (LE_GetSendResult(handle) != 0 && msg->result.pid > 0) {
26869570cc8Sopenharmony_ci        kill(msg->result.pid, SIGKILL);
26969570cc8Sopenharmony_ci    }
27069570cc8Sopenharmony_ci}
27169570cc8Sopenharmony_ci
27269570cc8Sopenharmony_cistatic int SendResponse(const AppSpawnConnection *connection, const AppSpawnMsg *msg, int result, pid_t pid)
27369570cc8Sopenharmony_ci{
27469570cc8Sopenharmony_ci    APPSPAWN_LOGV("SendResponse connectionId: %{public}u result: 0x%{public}x pid: %{public}d",
27569570cc8Sopenharmony_ci        connection->connectionId, result, pid);
27669570cc8Sopenharmony_ci    uint32_t bufferSize = sizeof(AppSpawnResponseMsg);
27769570cc8Sopenharmony_ci    BufferHandle handle = LE_CreateBuffer(LE_GetDefaultLoop(), bufferSize);
27869570cc8Sopenharmony_ci    AppSpawnResponseMsg *buffer = (AppSpawnResponseMsg *)LE_GetBufferInfo(handle, NULL, &bufferSize);
27969570cc8Sopenharmony_ci    int ret = memcpy_s(buffer, bufferSize, msg, sizeof(AppSpawnMsg));
28069570cc8Sopenharmony_ci    APPSPAWN_CHECK(ret == 0, LE_FreeBuffer(LE_GetDefaultLoop(), NULL, handle);
28169570cc8Sopenharmony_ci        return -1, "Failed to memcpy_s bufferSize");
28269570cc8Sopenharmony_ci    buffer->result.result = result;
28369570cc8Sopenharmony_ci    buffer->result.pid = pid;
28469570cc8Sopenharmony_ci    return LE_Send(LE_GetDefaultLoop(), connection->stream, handle, bufferSize);
28569570cc8Sopenharmony_ci}
28669570cc8Sopenharmony_ci
28769570cc8Sopenharmony_cistatic void WaitMsgCompleteTimeOut(const TimerHandle taskHandle, void *context)
28869570cc8Sopenharmony_ci{
28969570cc8Sopenharmony_ci    AppSpawnConnection *connection = (AppSpawnConnection *)context;
29069570cc8Sopenharmony_ci    APPSPAWN_LOGE("Long time no msg complete so close connectionId: %{public}u", connection->connectionId);
29169570cc8Sopenharmony_ci    DeleteAppSpawnMsg(connection->receiverCtx.incompleteMsg);
29269570cc8Sopenharmony_ci    connection->receiverCtx.incompleteMsg = NULL;
29369570cc8Sopenharmony_ci    LE_CloseStreamTask(LE_GetDefaultLoop(), connection->stream);
29469570cc8Sopenharmony_ci}
29569570cc8Sopenharmony_ci
29669570cc8Sopenharmony_cistatic inline int StartTimerForCheckMsg(AppSpawnConnection *connection)
29769570cc8Sopenharmony_ci{
29869570cc8Sopenharmony_ci    if (connection->receiverCtx.timer != NULL) {
29969570cc8Sopenharmony_ci        return 0;
30069570cc8Sopenharmony_ci    }
30169570cc8Sopenharmony_ci    int ret = LE_CreateTimer(LE_GetDefaultLoop(), &connection->receiverCtx.timer, WaitMsgCompleteTimeOut, connection);
30269570cc8Sopenharmony_ci    if (ret == 0) {
30369570cc8Sopenharmony_ci        ret = LE_StartTimer(LE_GetDefaultLoop(), connection->receiverCtx.timer, MAX_WAIT_MSG_COMPLETE, 1);
30469570cc8Sopenharmony_ci    }
30569570cc8Sopenharmony_ci    return ret;
30669570cc8Sopenharmony_ci}
30769570cc8Sopenharmony_ci
30869570cc8Sopenharmony_cistatic int HandleRecvMessage(const TaskHandle taskHandle, uint8_t * buffer, int bufferSize, int flags)
30969570cc8Sopenharmony_ci{
31069570cc8Sopenharmony_ci    int socketFd = LE_GetSocketFd(taskHandle);
31169570cc8Sopenharmony_ci    struct iovec iov = {
31269570cc8Sopenharmony_ci        .iov_base = buffer,
31369570cc8Sopenharmony_ci        .iov_len = bufferSize,
31469570cc8Sopenharmony_ci    };
31569570cc8Sopenharmony_ci    char ctrlBuffer[CMSG_SPACE(APP_MAX_FD_COUNT * sizeof(int))];
31669570cc8Sopenharmony_ci    struct msghdr msg = {
31769570cc8Sopenharmony_ci        .msg_iov = &iov,
31869570cc8Sopenharmony_ci        .msg_iovlen = 1,
31969570cc8Sopenharmony_ci        .msg_control = ctrlBuffer,
32069570cc8Sopenharmony_ci        .msg_controllen = sizeof(ctrlBuffer),
32169570cc8Sopenharmony_ci    };
32269570cc8Sopenharmony_ci
32369570cc8Sopenharmony_ci    AppSpawnConnection *connection = (AppSpawnConnection *) LE_GetUserData(taskHandle);
32469570cc8Sopenharmony_ci    APPSPAWN_CHECK(connection != NULL, return -1, "Invalid connection");
32569570cc8Sopenharmony_ci    errno = 0;
32669570cc8Sopenharmony_ci    int recvLen = recvmsg(socketFd, &msg, flags);
32769570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_LOG(errno == 0, "recvmsg with errno %{public}d", errno);
32869570cc8Sopenharmony_ci    struct cmsghdr *cmsg = NULL;
32969570cc8Sopenharmony_ci    for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
33069570cc8Sopenharmony_ci        if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
33169570cc8Sopenharmony_ci            int fdCount = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
33269570cc8Sopenharmony_ci            int *fd = (int *) CMSG_DATA(cmsg);
33369570cc8Sopenharmony_ci            APPSPAWN_CHECK(fdCount <= APP_MAX_FD_COUNT, return -1,
33469570cc8Sopenharmony_ci                "failed to recv fd %{public}d %{public}d", connection->receiverCtx.fdCount, fdCount);
33569570cc8Sopenharmony_ci            int ret = memcpy_s(connection->receiverCtx.fds,
33669570cc8Sopenharmony_ci                fdCount * sizeof(int), fd, fdCount * sizeof(int));
33769570cc8Sopenharmony_ci            APPSPAWN_CHECK(ret == 0, return -1, "memcpy_s fd ret %{public}d", ret);
33869570cc8Sopenharmony_ci            connection->receiverCtx.fdCount = fdCount;
33969570cc8Sopenharmony_ci        }
34069570cc8Sopenharmony_ci    }
34169570cc8Sopenharmony_ci
34269570cc8Sopenharmony_ci    return recvLen;
34369570cc8Sopenharmony_ci}
34469570cc8Sopenharmony_ci
34569570cc8Sopenharmony_ciAPPSPAWN_STATIC bool OnConnectionUserCheck(uid_t uid)
34669570cc8Sopenharmony_ci{
34769570cc8Sopenharmony_ci    const uid_t uids[APPSPAWN_MSG_USER_CHECK_COUNT] = {
34869570cc8Sopenharmony_ci        0, // root 0
34969570cc8Sopenharmony_ci        3350, // app_fwk_update 3350
35069570cc8Sopenharmony_ci        5523, // foundation 5523
35169570cc8Sopenharmony_ci    };
35269570cc8Sopenharmony_ci
35369570cc8Sopenharmony_ci    for (int i = 0; i < APPSPAWN_MSG_USER_CHECK_COUNT; i++) {
35469570cc8Sopenharmony_ci        if (uid == uids[i]) {
35569570cc8Sopenharmony_ci            return true;
35669570cc8Sopenharmony_ci        }
35769570cc8Sopenharmony_ci    }
35869570cc8Sopenharmony_ci
35969570cc8Sopenharmony_ci    // shell 2000
36069570cc8Sopenharmony_ci    if (uid == 2000 && IsDeveloperModeOpen()) {
36169570cc8Sopenharmony_ci        return true;
36269570cc8Sopenharmony_ci    }
36369570cc8Sopenharmony_ci
36469570cc8Sopenharmony_ci    return false;
36569570cc8Sopenharmony_ci}
36669570cc8Sopenharmony_ci
36769570cc8Sopenharmony_cistatic int OnConnection(const LoopHandle loopHandle, const TaskHandle server)
36869570cc8Sopenharmony_ci{
36969570cc8Sopenharmony_ci    APPSPAWN_CHECK(server != NULL && loopHandle != NULL, return -1, "Error server");
37069570cc8Sopenharmony_ci    static uint32_t connectionId = 0;
37169570cc8Sopenharmony_ci    TaskHandle stream;
37269570cc8Sopenharmony_ci    LE_StreamInfo info = {};
37369570cc8Sopenharmony_ci    info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_CONNECT;
37469570cc8Sopenharmony_ci    info.baseInfo.close = OnClose;
37569570cc8Sopenharmony_ci    info.baseInfo.userDataSize = sizeof(AppSpawnConnection);
37669570cc8Sopenharmony_ci    info.disConnectComplete = OnDisConnect;
37769570cc8Sopenharmony_ci    info.sendMessageComplete = SendMessageComplete;
37869570cc8Sopenharmony_ci    info.recvMessage = OnReceiveRequest;
37969570cc8Sopenharmony_ci    info.handleRecvMsg = HandleRecvMessage;
38069570cc8Sopenharmony_ci    LE_STATUS ret = LE_AcceptStreamClient(loopHandle, server, &stream, &info);
38169570cc8Sopenharmony_ci    APPSPAWN_CHECK(ret == 0, return -1, "Failed to alloc stream");
38269570cc8Sopenharmony_ci
38369570cc8Sopenharmony_ci    AppSpawnConnection *connection = (AppSpawnConnection *)LE_GetUserData(stream);
38469570cc8Sopenharmony_ci    APPSPAWN_CHECK(connection != NULL, return -1, "Failed to alloc stream");
38569570cc8Sopenharmony_ci    struct ucred cred = {-1, -1, -1};
38669570cc8Sopenharmony_ci    socklen_t credSize = sizeof(struct ucred);
38769570cc8Sopenharmony_ci    if ((getsockopt(LE_GetSocketFd(stream), SOL_SOCKET, SO_PEERCRED, &cred, &credSize) < 0) ||
38869570cc8Sopenharmony_ci        !OnConnectionUserCheck(cred.uid)) {
38969570cc8Sopenharmony_ci        APPSPAWN_LOGE("Invalid uid %{public}d from client", cred.uid);
39069570cc8Sopenharmony_ci        LE_CloseStreamTask(LE_GetDefaultLoop(), stream);
39169570cc8Sopenharmony_ci        return -1;
39269570cc8Sopenharmony_ci    }
39369570cc8Sopenharmony_ci    SetFdCtrl(LE_GetSocketFd(stream), FD_CLOEXEC);
39469570cc8Sopenharmony_ci
39569570cc8Sopenharmony_ci    connection->connectionId = ++connectionId;
39669570cc8Sopenharmony_ci    connection->stream = stream;
39769570cc8Sopenharmony_ci    connection->receiverCtx.fdCount = 0;
39869570cc8Sopenharmony_ci    connection->receiverCtx.incompleteMsg = NULL;
39969570cc8Sopenharmony_ci    connection->receiverCtx.timer = NULL;
40069570cc8Sopenharmony_ci    connection->receiverCtx.msgRecvLen = 0;
40169570cc8Sopenharmony_ci    connection->receiverCtx.nextMsgId = 1;
40269570cc8Sopenharmony_ci    APPSPAWN_LOGI("OnConnection connectionId: %{public}u fd %{public}d ",
40369570cc8Sopenharmony_ci        connection->connectionId, LE_GetSocketFd(stream));
40469570cc8Sopenharmony_ci    return 0;
40569570cc8Sopenharmony_ci}
40669570cc8Sopenharmony_ci
40769570cc8Sopenharmony_ciAPPSPAWN_STATIC bool MsgDevicedebugCheck(TaskHandle stream, AppSpawnMsgNode *message)
40869570cc8Sopenharmony_ci{
40969570cc8Sopenharmony_ci    struct ucred cred = {0, 0, 0};
41069570cc8Sopenharmony_ci    socklen_t credSize = sizeof(cred);
41169570cc8Sopenharmony_ci    if (getsockopt(LE_GetSocketFd(stream), SOL_SOCKET, SO_PEERCRED, &cred, &credSize) < 0) {
41269570cc8Sopenharmony_ci        return false;
41369570cc8Sopenharmony_ci    }
41469570cc8Sopenharmony_ci
41569570cc8Sopenharmony_ci    if (cred.uid != DecodeUid("shell")) {
41669570cc8Sopenharmony_ci        return true;
41769570cc8Sopenharmony_ci    }
41869570cc8Sopenharmony_ci
41969570cc8Sopenharmony_ci    AppSpawnMsg *msg = &message->msgHeader;
42069570cc8Sopenharmony_ci    if (msg->msgType != MSG_DEVICE_DEBUG) {
42169570cc8Sopenharmony_ci        APPSPAWN_LOGE("appspawn devicedebug msg type is not devicedebug [%{public}d]", msg->msgType);
42269570cc8Sopenharmony_ci        return false;
42369570cc8Sopenharmony_ci    }
42469570cc8Sopenharmony_ci
42569570cc8Sopenharmony_ci    return true;
42669570cc8Sopenharmony_ci}
42769570cc8Sopenharmony_ci
42869570cc8Sopenharmony_cistatic void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, uint32_t buffLen)
42969570cc8Sopenharmony_ci{
43069570cc8Sopenharmony_ci    AppSpawnConnection *connection = (AppSpawnConnection *)LE_GetUserData(taskHandle);
43169570cc8Sopenharmony_ci    APPSPAWN_CHECK(connection != NULL, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
43269570cc8Sopenharmony_ci        return, "Failed to get client form socket");
43369570cc8Sopenharmony_ci    APPSPAWN_CHECK(buffLen < MAX_MSG_TOTAL_LENGTH, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
43469570cc8Sopenharmony_ci        return, "Message too long %{public}u", buffLen);
43569570cc8Sopenharmony_ci
43669570cc8Sopenharmony_ci    uint32_t reminder = 0;
43769570cc8Sopenharmony_ci    uint32_t currLen = 0;
43869570cc8Sopenharmony_ci    AppSpawnMsgNode *message = connection->receiverCtx.incompleteMsg; // incomplete msg
43969570cc8Sopenharmony_ci    connection->receiverCtx.incompleteMsg = NULL;
44069570cc8Sopenharmony_ci    int ret = 0;
44169570cc8Sopenharmony_ci    do {
44269570cc8Sopenharmony_ci        APPSPAWN_LOGI("OnReceiveRequest connectionId: %{public}u start: 0x%{public}x buffLen %{public}d",
44369570cc8Sopenharmony_ci            connection->connectionId, *(uint32_t *)(buffer + currLen), buffLen - currLen);
44469570cc8Sopenharmony_ci
44569570cc8Sopenharmony_ci        ret = GetAppSpawnMsgFromBuffer(buffer + currLen, buffLen - currLen,
44669570cc8Sopenharmony_ci            &message, &connection->receiverCtx.msgRecvLen, &reminder);
44769570cc8Sopenharmony_ci        APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
44869570cc8Sopenharmony_ci
44969570cc8Sopenharmony_ci        if (connection->receiverCtx.msgRecvLen != message->msgHeader.msgLen) {  // recv complete msg
45069570cc8Sopenharmony_ci            connection->receiverCtx.incompleteMsg = message;
45169570cc8Sopenharmony_ci            message = NULL;
45269570cc8Sopenharmony_ci            break;
45369570cc8Sopenharmony_ci        }
45469570cc8Sopenharmony_ci        connection->receiverCtx.msgRecvLen = 0;
45569570cc8Sopenharmony_ci        if (connection->receiverCtx.timer) {
45669570cc8Sopenharmony_ci            LE_StopTimer(LE_GetDefaultLoop(), connection->receiverCtx.timer);
45769570cc8Sopenharmony_ci            connection->receiverCtx.timer = NULL;
45869570cc8Sopenharmony_ci        }
45969570cc8Sopenharmony_ci
46069570cc8Sopenharmony_ci        APPSPAWN_CHECK_ONLY_EXPER(MsgDevicedebugCheck(connection->stream, message),
46169570cc8Sopenharmony_ci            LE_CloseTask(LE_GetDefaultLoop(), taskHandle); return);
46269570cc8Sopenharmony_ci
46369570cc8Sopenharmony_ci        // decode msg
46469570cc8Sopenharmony_ci        ret = DecodeAppSpawnMsg(message);
46569570cc8Sopenharmony_ci        APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
46669570cc8Sopenharmony_ci        (void)ProcessRecvMsg(connection, message);
46769570cc8Sopenharmony_ci        message = NULL;
46869570cc8Sopenharmony_ci        currLen += buffLen - reminder;
46969570cc8Sopenharmony_ci    } while (reminder > 0);
47069570cc8Sopenharmony_ci
47169570cc8Sopenharmony_ci    if (message) {
47269570cc8Sopenharmony_ci        DeleteAppSpawnMsg(message);
47369570cc8Sopenharmony_ci    }
47469570cc8Sopenharmony_ci    if (ret != 0) {
47569570cc8Sopenharmony_ci        LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
47669570cc8Sopenharmony_ci        return;
47769570cc8Sopenharmony_ci    }
47869570cc8Sopenharmony_ci    if (connection->receiverCtx.incompleteMsg != NULL) { // Start the detection timer
47969570cc8Sopenharmony_ci        ret = StartTimerForCheckMsg(connection);
48069570cc8Sopenharmony_ci        APPSPAWN_CHECK(ret == 0, LE_CloseStreamTask(LE_GetDefaultLoop(), taskHandle);
48169570cc8Sopenharmony_ci            return, "Failed to create time for connection");
48269570cc8Sopenharmony_ci    }
48369570cc8Sopenharmony_ci    return;
48469570cc8Sopenharmony_ci}
48569570cc8Sopenharmony_ci
48669570cc8Sopenharmony_cistatic char *GetMapMem(uint32_t clientId, const char *processName, uint32_t size, bool readOnly, bool isNweb)
48769570cc8Sopenharmony_ci{
48869570cc8Sopenharmony_ci    char path[PATH_MAX] = {};
48969570cc8Sopenharmony_ci    int len = sprintf_s(path, sizeof(path), APPSPAWN_MSG_DIR "%s/%s_%u",
49069570cc8Sopenharmony_ci        isNweb ? "nwebspawn" : "appspawn", processName, clientId);
49169570cc8Sopenharmony_ci    APPSPAWN_CHECK(len > 0, return NULL, "Failed to format path %{public}s", processName);
49269570cc8Sopenharmony_ci    APPSPAWN_LOGV("GetMapMem for child %{public}s memSize %{public}u", path, size);
49369570cc8Sopenharmony_ci    int prot = PROT_READ;
49469570cc8Sopenharmony_ci    int mode = O_RDONLY;
49569570cc8Sopenharmony_ci    if (!readOnly) {
49669570cc8Sopenharmony_ci        mode = O_CREAT | O_RDWR | O_TRUNC;
49769570cc8Sopenharmony_ci        prot = PROT_READ | PROT_WRITE;
49869570cc8Sopenharmony_ci    }
49969570cc8Sopenharmony_ci    int fd = open(path, mode, S_IRWXU);
50069570cc8Sopenharmony_ci    APPSPAWN_CHECK(fd >= 0, return NULL, "Failed to open errno %{public}d path %{public}s", errno, path);
50169570cc8Sopenharmony_ci    if (!readOnly) {
50269570cc8Sopenharmony_ci        ftruncate(fd, size);
50369570cc8Sopenharmony_ci    }
50469570cc8Sopenharmony_ci    void *areaAddr = (void *)mmap(NULL, size, prot, MAP_SHARED, fd, 0);
50569570cc8Sopenharmony_ci    close(fd);
50669570cc8Sopenharmony_ci    APPSPAWN_CHECK(areaAddr != MAP_FAILED && areaAddr != NULL,
50769570cc8Sopenharmony_ci        return NULL, "Failed to map memory error %{public}d fileName %{public}s ", errno, path);
50869570cc8Sopenharmony_ci    return (char *)areaAddr;
50969570cc8Sopenharmony_ci}
51069570cc8Sopenharmony_ci
51169570cc8Sopenharmony_ciAPPSPAWN_STATIC int WriteMsgToChild(AppSpawningCtx *property, bool isNweb)
51269570cc8Sopenharmony_ci{
51369570cc8Sopenharmony_ci    APPSPAWN_CHECK(property != NULL && property->message != NULL, return APPSPAWN_MSG_INVALID,
51469570cc8Sopenharmony_ci        "Failed to WriteMsgToChild property invalid");
51569570cc8Sopenharmony_ci    const uint32_t memSize = (property->message->msgHeader.msgLen / 4096 + 1) * 4096; // 4096 4K
51669570cc8Sopenharmony_ci    char *buffer = GetMapMem(property->client.id, GetProcessName(property), memSize, false, isNweb);
51769570cc8Sopenharmony_ci    APPSPAWN_CHECK(buffer != NULL, return APPSPAWN_SYSTEM_ERROR,
51869570cc8Sopenharmony_ci        "Failed to map memory error %{public}d fileName %{public}s ", errno, GetProcessName(property));
51969570cc8Sopenharmony_ci    // copy msg header
52069570cc8Sopenharmony_ci    int ret = memcpy_s(buffer, memSize, &property->message->msgHeader, sizeof(AppSpawnMsg));
52169570cc8Sopenharmony_ci    if (ret == 0) {
52269570cc8Sopenharmony_ci        ret = memcpy_s((char *)buffer + sizeof(AppSpawnMsg), memSize - sizeof(AppSpawnMsg),
52369570cc8Sopenharmony_ci            property->message->buffer, property->message->msgHeader.msgLen - sizeof(AppSpawnMsg));
52469570cc8Sopenharmony_ci    }
52569570cc8Sopenharmony_ci    if (ret != 0) {
52669570cc8Sopenharmony_ci        APPSPAWN_LOGE("Failed to copy msg fileName %{public}s ", GetProcessName(property));
52769570cc8Sopenharmony_ci        munmap((char *)buffer, memSize);
52869570cc8Sopenharmony_ci        return APPSPAWN_SYSTEM_ERROR;
52969570cc8Sopenharmony_ci    }
53069570cc8Sopenharmony_ci    property->forkCtx.msgSize = memSize;
53169570cc8Sopenharmony_ci    property->forkCtx.childMsg = buffer;
53269570cc8Sopenharmony_ci    APPSPAWN_LOGV("Write msg to child: %{public}u success", property->client.id);
53369570cc8Sopenharmony_ci    return 0;
53469570cc8Sopenharmony_ci}
53569570cc8Sopenharmony_ci
53669570cc8Sopenharmony_cistatic int InitForkContext(AppSpawningCtx *property)
53769570cc8Sopenharmony_ci{
53869570cc8Sopenharmony_ci    if (pipe(property->forkCtx.fd) == -1) {
53969570cc8Sopenharmony_ci        APPSPAWN_LOGE("create pipe fail, errno: %{public}d", errno);
54069570cc8Sopenharmony_ci        return errno;
54169570cc8Sopenharmony_ci    }
54269570cc8Sopenharmony_ci    int option = fcntl(property->forkCtx.fd[0], F_GETFD);
54369570cc8Sopenharmony_ci    if (option > 0) {
54469570cc8Sopenharmony_ci        (void)fcntl(property->forkCtx.fd[0], F_SETFD, (unsigned int)option | O_NONBLOCK);
54569570cc8Sopenharmony_ci    }
54669570cc8Sopenharmony_ci    return 0;
54769570cc8Sopenharmony_ci}
54869570cc8Sopenharmony_ci
54969570cc8Sopenharmony_cistatic void ClosePidfdWatcher(const TaskHandle taskHandle)
55069570cc8Sopenharmony_ci{
55169570cc8Sopenharmony_ci    int fd = LE_GetSocketFd(taskHandle);
55269570cc8Sopenharmony_ci    if (fd >= 0) {
55369570cc8Sopenharmony_ci        close(fd);
55469570cc8Sopenharmony_ci    }
55569570cc8Sopenharmony_ci    void *p = LE_GetUserData(taskHandle);
55669570cc8Sopenharmony_ci    if (p != NULL) {
55769570cc8Sopenharmony_ci        free(*(void **)p);
55869570cc8Sopenharmony_ci    }
55969570cc8Sopenharmony_ci}
56069570cc8Sopenharmony_ci
56169570cc8Sopenharmony_cistatic void ProcessChildProcessFd(const WatcherHandle taskHandle, int fd, uint32_t *events, const void *context)
56269570cc8Sopenharmony_ci{
56369570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(context != NULL, return);
56469570cc8Sopenharmony_ci    pid_t pid = *(pid_t *)context;
56569570cc8Sopenharmony_ci    APPSPAWN_LOGI("Kill process group with process group id %{public}d, pidFd %{public}d", pid, fd);
56669570cc8Sopenharmony_ci    AppSpawnedProcess *appInfo = GetSpawnedProcess(pid);
56769570cc8Sopenharmony_ci    if (appInfo == NULL) {
56869570cc8Sopenharmony_ci        APPSPAWN_LOGW("Cannot get app info by bundle name: %{public}d", pid);
56969570cc8Sopenharmony_ci        return;
57069570cc8Sopenharmony_ci    }
57169570cc8Sopenharmony_ci    ProcessMgrHookExecute(STAGE_SERVER_APP_DIED, GetAppSpawnContent(), appInfo);
57269570cc8Sopenharmony_ci    LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
57369570cc8Sopenharmony_ci}
57469570cc8Sopenharmony_ci
57569570cc8Sopenharmony_cistatic int OpenPidFd(pid_t pid, unsigned int flags)
57669570cc8Sopenharmony_ci{
57769570cc8Sopenharmony_ci    return syscall(SYS_pidfd_open, pid, flags);
57869570cc8Sopenharmony_ci}
57969570cc8Sopenharmony_ci
58069570cc8Sopenharmony_cistatic void WatchChildProcessFd(AppSpawningCtx *property)
58169570cc8Sopenharmony_ci{
58269570cc8Sopenharmony_ci    if (property->pid <= 0) {
58369570cc8Sopenharmony_ci        APPSPAWN_LOGW("Invalid child process pid, skip watch");
58469570cc8Sopenharmony_ci        return;
58569570cc8Sopenharmony_ci    }
58669570cc8Sopenharmony_ci    if (IsNWebSpawnMode((AppSpawnMgr *)GetAppSpawnContent())) {
58769570cc8Sopenharmony_ci        APPSPAWN_LOGV("Nwebspawn don't need add pidfd");
58869570cc8Sopenharmony_ci        return;
58969570cc8Sopenharmony_ci    }
59069570cc8Sopenharmony_ci    AppSpawnedProcess *appInfo = GetSpawnedProcess(property->pid);
59169570cc8Sopenharmony_ci    if (appInfo == NULL) {
59269570cc8Sopenharmony_ci        APPSPAWN_LOGW("Cannot get app info of pid %{public}d", property->pid);
59369570cc8Sopenharmony_ci        return;
59469570cc8Sopenharmony_ci    }
59569570cc8Sopenharmony_ci    int fd = OpenPidFd(property->pid, PIDFD_NONBLOCK); // PIDFD_NONBLOCK  since Linux kernel 5.10
59669570cc8Sopenharmony_ci    if (fd < 0) {
59769570cc8Sopenharmony_ci        APPSPAWN_LOGW("Failed to open pid fd for app: %{public}s, err = %{public}d",
59869570cc8Sopenharmony_ci            GetBundleName(property), errno);
59969570cc8Sopenharmony_ci        return;
60069570cc8Sopenharmony_ci    }
60169570cc8Sopenharmony_ci    APPSPAWN_LOGI("watch app process pid %{public}d, pidFd %{public}d", property->pid, fd);
60269570cc8Sopenharmony_ci    LE_WatchInfo watchInfo = {};
60369570cc8Sopenharmony_ci    watchInfo.fd = fd;
60469570cc8Sopenharmony_ci    watchInfo.flags = WATCHER_ONCE;
60569570cc8Sopenharmony_ci    watchInfo.events = EVENT_READ;
60669570cc8Sopenharmony_ci    watchInfo.close = ClosePidfdWatcher;
60769570cc8Sopenharmony_ci    watchInfo.processEvent = ProcessChildProcessFd;
60869570cc8Sopenharmony_ci
60969570cc8Sopenharmony_ci    pid_t *appPid = (pid_t *)malloc(sizeof(pid_t));
61069570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(appPid != NULL, return);
61169570cc8Sopenharmony_ci    *appPid = property->pid;
61269570cc8Sopenharmony_ci    LE_STATUS status = LE_StartWatcher(LE_GetDefaultLoop(), &property->forkCtx.pidFdWatcherHandle, &watchInfo, appPid);
61369570cc8Sopenharmony_ci    if (status != LE_SUCCESS) {
61469570cc8Sopenharmony_ci#ifndef APPSPAWN_TEST
61569570cc8Sopenharmony_ci        close(fd);
61669570cc8Sopenharmony_ci#endif
61769570cc8Sopenharmony_ci        APPSPAWN_LOGW("Failed to watch child pid fd, pid is %{public}d", property->pid);
61869570cc8Sopenharmony_ci    }
61969570cc8Sopenharmony_ci}
62069570cc8Sopenharmony_ci
62169570cc8Sopenharmony_cistatic int IsChildColdRun(AppSpawningCtx *property)
62269570cc8Sopenharmony_ci{
62369570cc8Sopenharmony_ci    return CheckAppMsgFlagsSet(property, APP_FLAGS_UBSAN_ENABLED)
62469570cc8Sopenharmony_ci        || CheckAppMsgFlagsSet(property, APP_FLAGS_ASANENABLED)
62569570cc8Sopenharmony_ci        || CheckAppMsgFlagsSet(property, APP_FLAGS_TSAN_ENABLED)
62669570cc8Sopenharmony_ci        || CheckAppMsgFlagsSet(property, APP_FLAGS_HWASAN_ENABLED)
62769570cc8Sopenharmony_ci        || (property->client.flags & APP_COLD_START);
62869570cc8Sopenharmony_ci}
62969570cc8Sopenharmony_ci
63069570cc8Sopenharmony_cistatic int AddChildWatcher(AppSpawningCtx *property)
63169570cc8Sopenharmony_ci{
63269570cc8Sopenharmony_ci    uint32_t defTimeout = IsChildColdRun(property) ? COLD_CHILD_RESPONSE_TIMEOUT : WAIT_CHILD_RESPONSE_TIMEOUT;
63369570cc8Sopenharmony_ci    uint32_t timeout = GetSpawnTimeout(defTimeout);
63469570cc8Sopenharmony_ci    LE_WatchInfo watchInfo = {};
63569570cc8Sopenharmony_ci    watchInfo.fd = property->forkCtx.fd[0];
63669570cc8Sopenharmony_ci    watchInfo.flags = WATCHER_ONCE;
63769570cc8Sopenharmony_ci    watchInfo.events = EVENT_READ;
63869570cc8Sopenharmony_ci    watchInfo.processEvent = ProcessChildResponse;
63969570cc8Sopenharmony_ci    LE_STATUS status = LE_StartWatcher(LE_GetDefaultLoop(), &property->forkCtx.watcherHandle, &watchInfo, property);
64069570cc8Sopenharmony_ci    APPSPAWN_CHECK(status == LE_SUCCESS,
64169570cc8Sopenharmony_ci        return APPSPAWN_SYSTEM_ERROR, "Failed to watch child %{public}d", property->pid);
64269570cc8Sopenharmony_ci    status = LE_CreateTimer(LE_GetDefaultLoop(), &property->forkCtx.timer, WaitChildTimeout, property);
64369570cc8Sopenharmony_ci    if (status == LE_SUCCESS) {
64469570cc8Sopenharmony_ci        status = LE_StartTimer(LE_GetDefaultLoop(), property->forkCtx.timer, timeout * 1000, 0); // 1000 1s
64569570cc8Sopenharmony_ci    }
64669570cc8Sopenharmony_ci    if (status != LE_SUCCESS) {
64769570cc8Sopenharmony_ci        if (property->forkCtx.timer != NULL) {
64869570cc8Sopenharmony_ci            LE_StopTimer(LE_GetDefaultLoop(), property->forkCtx.timer);
64969570cc8Sopenharmony_ci        }
65069570cc8Sopenharmony_ci        property->forkCtx.timer = NULL;
65169570cc8Sopenharmony_ci        LE_RemoveWatcher(LE_GetDefaultLoop(), property->forkCtx.watcherHandle);
65269570cc8Sopenharmony_ci        property->forkCtx.watcherHandle = NULL;
65369570cc8Sopenharmony_ci        APPSPAWN_LOGE("Failed to watch child %{public}d", property->pid);
65469570cc8Sopenharmony_ci        return APPSPAWN_SYSTEM_ERROR;
65569570cc8Sopenharmony_ci    }
65669570cc8Sopenharmony_ci    return 0;
65769570cc8Sopenharmony_ci}
65869570cc8Sopenharmony_ci
65969570cc8Sopenharmony_cistatic bool IsSupportRunHnp()
66069570cc8Sopenharmony_ci{
66169570cc8Sopenharmony_ci    char buffer[PARAM_BUFFER_SIZE] = {0};
66269570cc8Sopenharmony_ci    int ret = GetParameter("const.startup.hnp.execute.enable", "false", buffer, PARAM_BUFFER_SIZE);
66369570cc8Sopenharmony_ci    if (ret <= 0) {
66469570cc8Sopenharmony_ci        APPSPAWN_LOGE("Get hnp execute enable param unsuccess! ret =%{public}d", ret);
66569570cc8Sopenharmony_ci        return false;
66669570cc8Sopenharmony_ci    }
66769570cc8Sopenharmony_ci
66869570cc8Sopenharmony_ci    if (strcmp(buffer, "true") == 0) {
66969570cc8Sopenharmony_ci        return true;
67069570cc8Sopenharmony_ci    }
67169570cc8Sopenharmony_ci
67269570cc8Sopenharmony_ci    return false;
67369570cc8Sopenharmony_ci}
67469570cc8Sopenharmony_ci
67569570cc8Sopenharmony_cistatic int WritePreforkMsg(AppSpawningCtx *property)
67669570cc8Sopenharmony_ci{
67769570cc8Sopenharmony_ci    AppSpawnContent *content = GetAppSpawnContent();
67869570cc8Sopenharmony_ci    if (content == NULL || content->propertyBuffer == NULL) {
67969570cc8Sopenharmony_ci        APPSPAWN_LOGE("buffer is null can not write propery");
68069570cc8Sopenharmony_ci        return  -1;
68169570cc8Sopenharmony_ci    }
68269570cc8Sopenharmony_ci
68369570cc8Sopenharmony_ci    int ret = memcpy_s(content->propertyBuffer, MAX_MEM_SIZE, &property->message->msgHeader, sizeof(AppSpawnMsg));
68469570cc8Sopenharmony_ci    APPSPAWN_CHECK(ret == 0, goto fail, "memcpys_s msgHeader failed");
68569570cc8Sopenharmony_ci    ret = memcpy_s((char *)content->propertyBuffer + sizeof(AppSpawnMsg), MAX_MEM_SIZE - sizeof(AppSpawnMsg),
68669570cc8Sopenharmony_ci        property->message->buffer, property->message->msgHeader.msgLen - sizeof(AppSpawnMsg));
68769570cc8Sopenharmony_ci    APPSPAWN_CHECK(ret == 0, goto fail, "memcpys_s AppSpawnMsg failed");
68869570cc8Sopenharmony_ci    return ret;
68969570cc8Sopenharmony_ci
69069570cc8Sopenharmony_cifail:
69169570cc8Sopenharmony_ci    munmap((char *)content->propertyBuffer, MAX_MEM_SIZE);
69269570cc8Sopenharmony_ci    content->propertyBuffer = NULL;
69369570cc8Sopenharmony_ci    return ret;
69469570cc8Sopenharmony_ci}
69569570cc8Sopenharmony_ci
69669570cc8Sopenharmony_cistatic int GetAppSpawnMsg(AppSpawningCtx *property)
69769570cc8Sopenharmony_ci{
69869570cc8Sopenharmony_ci    uint8_t *buffer = (uint8_t *)GetMapMem(property->client.id, "prefork", MAX_MEM_SIZE, true, false);
69969570cc8Sopenharmony_ci    if (buffer == NULL) {
70069570cc8Sopenharmony_ci        APPSPAWN_LOGE("prefork buffer is null can not write propery");
70169570cc8Sopenharmony_ci        return  -1;
70269570cc8Sopenharmony_ci    }
70369570cc8Sopenharmony_ci    uint32_t msgRecvLen = 0;
70469570cc8Sopenharmony_ci    uint32_t remainLen = 0;
70569570cc8Sopenharmony_ci    property->forkCtx.childMsg = (char *)buffer;
70669570cc8Sopenharmony_ci    property->forkCtx.msgSize = MAX_MEM_SIZE;
70769570cc8Sopenharmony_ci    AppSpawnMsgNode *message = NULL;
70869570cc8Sopenharmony_ci    int ret = GetAppSpawnMsgFromBuffer(buffer, ((AppSpawnMsg *)buffer)->msgLen, &message, &msgRecvLen, &remainLen);
70969570cc8Sopenharmony_ci    // release map
71069570cc8Sopenharmony_ci    APPSPAWN_LOGV("prefork GetAppSpawnMsg ret:%{public}d", ret);
71169570cc8Sopenharmony_ci    if (ret == 0 && DecodeAppSpawnMsg(message) == 0 && CheckAppSpawnMsg(message) == 0) {
71269570cc8Sopenharmony_ci        property->message = message;
71369570cc8Sopenharmony_ci        message = NULL;
71469570cc8Sopenharmony_ci        return 0;
71569570cc8Sopenharmony_ci    }
71669570cc8Sopenharmony_ci    return -1;
71769570cc8Sopenharmony_ci}
71869570cc8Sopenharmony_ci
71969570cc8Sopenharmony_cistatic void ClearMMAP(int clientId)
72069570cc8Sopenharmony_ci{
72169570cc8Sopenharmony_ci    char path[PATH_MAX] = {0};
72269570cc8Sopenharmony_ci    int ret = snprintf_s(path, sizeof(path), sizeof(path) - 1, APPSPAWN_MSG_DIR "appspawn/prefork_%d", clientId);
72369570cc8Sopenharmony_ci    APPSPAWN_LOGV("prefork unlink %{public}s ret :%{public}d", path, ret);
72469570cc8Sopenharmony_ci    if (ret > 0) {
72569570cc8Sopenharmony_ci        errno = 0;
72669570cc8Sopenharmony_ci        ret =  unlink(path);
72769570cc8Sopenharmony_ci        APPSPAWN_LOGV("prefork unlink result %{public}d %{public}d", ret, errno);
72869570cc8Sopenharmony_ci    }
72969570cc8Sopenharmony_ci
73069570cc8Sopenharmony_ci    AppSpawnContent *content = GetAppSpawnContent();
73169570cc8Sopenharmony_ci    if (content != NULL && content->propertyBuffer != NULL) {
73269570cc8Sopenharmony_ci        ret = munmap(content->propertyBuffer, MAX_MEM_SIZE);
73369570cc8Sopenharmony_ci        APPSPAWN_CHECK_ONLY_LOG(ret == 0, "munmap failed %{public}d", ret);
73469570cc8Sopenharmony_ci        content->propertyBuffer = NULL;
73569570cc8Sopenharmony_ci    }
73669570cc8Sopenharmony_ci}
73769570cc8Sopenharmony_ci
73869570cc8Sopenharmony_cistatic int SetPreforkProcessName(AppSpawnContent *content)
73969570cc8Sopenharmony_ci{
74069570cc8Sopenharmony_ci    int ret = prctl(PR_SET_NAME, PREFORK_PROCESS);
74169570cc8Sopenharmony_ci    if (ret == -1) {
74269570cc8Sopenharmony_ci        return errno;
74369570cc8Sopenharmony_ci    }
74469570cc8Sopenharmony_ci
74569570cc8Sopenharmony_ci    ret = memset_s(content->longProcName,
74669570cc8Sopenharmony_ci        (size_t)content->longProcNameLen, 0, (size_t)content->longProcNameLen);
74769570cc8Sopenharmony_ci    if (ret != EOK) {
74869570cc8Sopenharmony_ci        return EINVAL;
74969570cc8Sopenharmony_ci    }
75069570cc8Sopenharmony_ci
75169570cc8Sopenharmony_ci    ret = strncpy_s(content->longProcName, content->longProcNameLen,
75269570cc8Sopenharmony_ci        PREFORK_PROCESS, strlen(PREFORK_PROCESS));
75369570cc8Sopenharmony_ci    if (ret != EOK) {
75469570cc8Sopenharmony_ci        return EINVAL;
75569570cc8Sopenharmony_ci    }
75669570cc8Sopenharmony_ci
75769570cc8Sopenharmony_ci    return 0;
75869570cc8Sopenharmony_ci}
75969570cc8Sopenharmony_ci
76069570cc8Sopenharmony_cistatic void ProcessPreFork(AppSpawnContent *content, AppSpawningCtx *property)
76169570cc8Sopenharmony_ci{
76269570cc8Sopenharmony_ci    APPSPAWN_CHECK(pipe(content->preforkFd) == 0, return, "prefork with prefork pipe failed %{public}d", errno);
76369570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(content->parentToChildFd[0] <= 0, close(content->parentToChildFd[0]);
76469570cc8Sopenharmony_ci        content->parentToChildFd[0] = -1);
76569570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(content->parentToChildFd[1] <= 0, close(content->parentToChildFd[1]);
76669570cc8Sopenharmony_ci        content->parentToChildFd[1] = -1);
76769570cc8Sopenharmony_ci    APPSPAWN_CHECK(pipe(content->parentToChildFd) == 0, return, "prefork with prefork pipe failed %{public}d", errno);
76869570cc8Sopenharmony_ci
76969570cc8Sopenharmony_ci    content->reservedPid = fork();
77069570cc8Sopenharmony_ci    APPSPAWN_LOGV("prefork fork finish %{public}d,%{public}d,%{public}d,%{public}d,%{public}d",
77169570cc8Sopenharmony_ci        content->reservedPid, content->preforkFd[0], content->preforkFd[1], content->parentToChildFd[0],
77269570cc8Sopenharmony_ci        content->parentToChildFd[1]);
77369570cc8Sopenharmony_ci    if (content->reservedPid == 0) {
77469570cc8Sopenharmony_ci        (void)close(property->forkCtx.fd[0]);
77569570cc8Sopenharmony_ci        (void)close(property->forkCtx.fd[1]);
77669570cc8Sopenharmony_ci        int isRet = SetPreforkProcessName(content);
77769570cc8Sopenharmony_ci        APPSPAWN_LOGI("prefork process start wait read msg with set processname %{public}d", isRet);
77869570cc8Sopenharmony_ci        AppSpawnClient client = {0, 0};
77969570cc8Sopenharmony_ci        int infoSize = read(content->parentToChildFd[0], &client, sizeof(AppSpawnClient));
78069570cc8Sopenharmony_ci        if (infoSize != sizeof(AppSpawnClient)) {
78169570cc8Sopenharmony_ci            APPSPAWN_LOGE("prefork process read msg failed %{public}d,%{public}d", infoSize, errno);
78269570cc8Sopenharmony_ci            ProcessExit(0);
78369570cc8Sopenharmony_ci            return;
78469570cc8Sopenharmony_ci        }
78569570cc8Sopenharmony_ci        property->client.id = client.id;
78669570cc8Sopenharmony_ci        property->client.flags = client.flags;
78769570cc8Sopenharmony_ci        property->isPrefork = true;
78869570cc8Sopenharmony_ci        property->forkCtx.fd[0] = content->preforkFd[0];
78969570cc8Sopenharmony_ci        property->forkCtx.fd[1] = content->preforkFd[1];
79069570cc8Sopenharmony_ci        property->state = APP_STATE_SPAWNING;
79169570cc8Sopenharmony_ci        if (GetAppSpawnMsg(property) == -1) {
79269570cc8Sopenharmony_ci            APPSPAWN_LOGE("prefork child read GetAppSpawnMsg failed");
79369570cc8Sopenharmony_ci            ClearMMAP(property->client.id);
79469570cc8Sopenharmony_ci            content->notifyResToParent(content, &property->client, APPSPAWN_MSG_INVALID);
79569570cc8Sopenharmony_ci            ProcessExit(0);
79669570cc8Sopenharmony_ci            return;
79769570cc8Sopenharmony_ci        }
79869570cc8Sopenharmony_ci        ClearMMAP(property->client.id);
79969570cc8Sopenharmony_ci        ProcessExit(AppSpawnChild(content, &property->client));
80069570cc8Sopenharmony_ci    } else if (content->reservedPid < 0) {
80169570cc8Sopenharmony_ci        APPSPAWN_LOGE("prefork fork child process failed %{public}d", content->reservedPid);
80269570cc8Sopenharmony_ci    }
80369570cc8Sopenharmony_ci}
80469570cc8Sopenharmony_ci
80569570cc8Sopenharmony_cistatic int AppSpawnProcessMsgForPrefork(AppSpawnContent *content, AppSpawnClient *client, pid_t *childPid)
80669570cc8Sopenharmony_ci{
80769570cc8Sopenharmony_ci    int ret = 0;
80869570cc8Sopenharmony_ci    AppSpawningCtx *property = (AppSpawningCtx *)client;
80969570cc8Sopenharmony_ci
81069570cc8Sopenharmony_ci    if (content->reservedPid <= 0) {
81169570cc8Sopenharmony_ci        APPSPAWN_CHECK(client != NULL, return ret, "client is null");
81269570cc8Sopenharmony_ci        ret = InitForkContext((AppSpawningCtx *)client);
81369570cc8Sopenharmony_ci        APPSPAWN_CHECK(ret == 0, return ret, "init fork context failed");
81469570cc8Sopenharmony_ci        ret = AppSpawnProcessMsg(content, client, childPid);
81569570cc8Sopenharmony_ci    } else {
81669570cc8Sopenharmony_ci        APPSPAWN_CHECK_ONLY_EXPER(content->propertyBuffer == NULL, ClearMMAP(client->id));
81769570cc8Sopenharmony_ci        content->propertyBuffer = GetMapMem(property->client.id, "prefork", MAX_MEM_SIZE, false, false);
81869570cc8Sopenharmony_ci        APPSPAWN_CHECK(content->propertyBuffer != NULL, return -1, "GetPreforkMem failed");
81969570cc8Sopenharmony_ci        ret = WritePreforkMsg(property);
82069570cc8Sopenharmony_ci        APPSPAWN_CHECK(ret == 0, return ret, "WritePreforkMsg failed");
82169570cc8Sopenharmony_ci
82269570cc8Sopenharmony_ci        *childPid = content->reservedPid;
82369570cc8Sopenharmony_ci        property->forkCtx.fd[0] = content->preforkFd[0];
82469570cc8Sopenharmony_ci        property->forkCtx.fd[1] = content->preforkFd[1];
82569570cc8Sopenharmony_ci
82669570cc8Sopenharmony_ci        int option = fcntl(property->forkCtx.fd[0], F_GETFD);
82769570cc8Sopenharmony_ci        if (option > 0) {
82869570cc8Sopenharmony_ci            ret = fcntl(property->forkCtx.fd[0], F_SETFD, (unsigned int)option | O_NONBLOCK);
82969570cc8Sopenharmony_ci            APPSPAWN_CHECK_ONLY_LOG(ret == 0, "fcntl failed %{public}d,%{public}d", ret, errno);
83069570cc8Sopenharmony_ci        }
83169570cc8Sopenharmony_ci
83269570cc8Sopenharmony_ci        ssize_t writesize = write(content->parentToChildFd[1], client, sizeof(AppSpawnClient)) ;
83369570cc8Sopenharmony_ci        APPSPAWN_CHECK(writesize == sizeof(AppSpawnClient), kill(*childPid, SIGKILL);
83469570cc8Sopenharmony_ci            *childPid = 0;
83569570cc8Sopenharmony_ci            ret = -1,
83669570cc8Sopenharmony_ci            "write msg to child failed %{public}d", errno);
83769570cc8Sopenharmony_ci    }
83869570cc8Sopenharmony_ci    ProcessPreFork(content, property);
83969570cc8Sopenharmony_ci    return ret;
84069570cc8Sopenharmony_ci}
84169570cc8Sopenharmony_ci
84269570cc8Sopenharmony_cistatic bool IsSupportPrefork(AppSpawnContent *content, AppSpawnClient *client)
84369570cc8Sopenharmony_ci{
84469570cc8Sopenharmony_ci#ifdef APPSPAWN_SUPPORT_PREFORK
84569570cc8Sopenharmony_ci    if (client == NULL || content == NULL) {
84669570cc8Sopenharmony_ci        return false;
84769570cc8Sopenharmony_ci    }
84869570cc8Sopenharmony_ci    if (!content->enablePerfork) {
84969570cc8Sopenharmony_ci        return false;
85069570cc8Sopenharmony_ci    }
85169570cc8Sopenharmony_ci    AppSpawningCtx *property = (AppSpawningCtx *)client;
85269570cc8Sopenharmony_ci
85369570cc8Sopenharmony_ci    if (content->mode == MODE_FOR_APP_SPAWN && !IsChildColdRun(property)
85469570cc8Sopenharmony_ci        && !CheckAppMsgFlagsSet(property, APP_FLAGS_CHILDPROCESS)) {
85569570cc8Sopenharmony_ci        return true;
85669570cc8Sopenharmony_ci    }
85769570cc8Sopenharmony_ci#endif
85869570cc8Sopenharmony_ci    return false;
85969570cc8Sopenharmony_ci}
86069570cc8Sopenharmony_ci
86169570cc8Sopenharmony_cistatic bool IsBootFinished()
86269570cc8Sopenharmony_ci{
86369570cc8Sopenharmony_ci    char buffer[32] = {0};  // 32 max
86469570cc8Sopenharmony_ci    int ret = GetParameter("bootevent.boot.completed", "false", buffer, sizeof(buffer));
86569570cc8Sopenharmony_ci    bool isBootCompleted = (ret > 0 && strcmp(buffer, "true") == 0);
86669570cc8Sopenharmony_ci    return isBootCompleted;
86769570cc8Sopenharmony_ci}
86869570cc8Sopenharmony_ci
86969570cc8Sopenharmony_cistatic int RunAppSpawnProcessMsg(AppSpawnContent *content, AppSpawnClient *client, pid_t *childPid)
87069570cc8Sopenharmony_ci{
87169570cc8Sopenharmony_ci    int ret = 0;
87269570cc8Sopenharmony_ci
87369570cc8Sopenharmony_ci    if (IsBootFinished() && IsSupportPrefork(content, client)) {
87469570cc8Sopenharmony_ci        ret = AppSpawnProcessMsgForPrefork(content, client, childPid);
87569570cc8Sopenharmony_ci    } else {
87669570cc8Sopenharmony_ci        APPSPAWN_CHECK(client != NULL, return ret, "client is null");
87769570cc8Sopenharmony_ci        ret = InitForkContext((AppSpawningCtx *)client);
87869570cc8Sopenharmony_ci        APPSPAWN_CHECK(ret == 0, return ret, "init fork context failed");
87969570cc8Sopenharmony_ci        ret = AppSpawnProcessMsg(content, client, childPid);
88069570cc8Sopenharmony_ci    }
88169570cc8Sopenharmony_ci    return ret;
88269570cc8Sopenharmony_ci}
88369570cc8Sopenharmony_ci
88469570cc8Sopenharmony_cistatic void ProcessSpawnReqMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message)
88569570cc8Sopenharmony_ci{
88669570cc8Sopenharmony_ci    int ret = CheckAppSpawnMsg(message);
88769570cc8Sopenharmony_ci    if (ret != 0) {
88869570cc8Sopenharmony_ci        SendResponse(connection, &message->msgHeader, ret, 0);
88969570cc8Sopenharmony_ci        DeleteAppSpawnMsg(message);
89069570cc8Sopenharmony_ci        return;
89169570cc8Sopenharmony_ci    }
89269570cc8Sopenharmony_ci
89369570cc8Sopenharmony_ci    if (IsDeveloperModeOpen()) {
89469570cc8Sopenharmony_ci        if (IsSupportRunHnp()) {
89569570cc8Sopenharmony_ci            SetAppSpawnMsgFlag(message, TLV_MSG_FLAGS, APP_FLAGS_DEVELOPER_MODE);
89669570cc8Sopenharmony_ci        } else {
89769570cc8Sopenharmony_ci            APPSPAWN_LOGI("Not support execute hnp file!");
89869570cc8Sopenharmony_ci        }
89969570cc8Sopenharmony_ci    }
90069570cc8Sopenharmony_ci
90169570cc8Sopenharmony_ci    AppSpawningCtx *property = CreateAppSpawningCtx();
90269570cc8Sopenharmony_ci    if (property == NULL) {
90369570cc8Sopenharmony_ci        SendResponse(connection, &message->msgHeader, APPSPAWN_SYSTEM_ERROR, 0);
90469570cc8Sopenharmony_ci        DeleteAppSpawnMsg(message);
90569570cc8Sopenharmony_ci        return;
90669570cc8Sopenharmony_ci    }
90769570cc8Sopenharmony_ci
90869570cc8Sopenharmony_ci    property->state = APP_STATE_SPAWNING;
90969570cc8Sopenharmony_ci    property->message = message;
91069570cc8Sopenharmony_ci    message->connection = connection;
91169570cc8Sopenharmony_ci    // mount el2 dir
91269570cc8Sopenharmony_ci    // getWrapBundleNameValue
91369570cc8Sopenharmony_ci    AppSpawnHookExecute(STAGE_PARENT_PRE_FORK, 0, GetAppSpawnContent(), &property->client);
91469570cc8Sopenharmony_ci    DumpAppSpawnMsg(property->message);
91569570cc8Sopenharmony_ci
91669570cc8Sopenharmony_ci    clock_gettime(CLOCK_MONOTONIC, &property->spawnStart);
91769570cc8Sopenharmony_ci    ret = RunAppSpawnProcessMsg(GetAppSpawnContent(), &property->client, &property->pid);
91869570cc8Sopenharmony_ci    AppSpawnHookExecute(STAGE_PARENT_POST_FORK, 0, GetAppSpawnContent(), &property->client);
91969570cc8Sopenharmony_ci    if (ret != 0) { // wait child process result
92069570cc8Sopenharmony_ci        SendResponse(connection, &message->msgHeader, ret, 0);
92169570cc8Sopenharmony_ci        DeleteAppSpawningCtx(property);
92269570cc8Sopenharmony_ci        return;
92369570cc8Sopenharmony_ci    }
92469570cc8Sopenharmony_ci    if (AddChildWatcher(property) != 0) { // wait child process result
92569570cc8Sopenharmony_ci        kill(property->pid, SIGKILL);
92669570cc8Sopenharmony_ci        SendResponse(connection, &message->msgHeader, ret, 0);
92769570cc8Sopenharmony_ci        DeleteAppSpawningCtx(property);
92869570cc8Sopenharmony_ci        return;
92969570cc8Sopenharmony_ci    }
93069570cc8Sopenharmony_ci}
93169570cc8Sopenharmony_ci
93269570cc8Sopenharmony_cistatic uint32_t g_lastDiedAppId = 0;
93369570cc8Sopenharmony_cistatic uint32_t g_crashTimes = 0;
93469570cc8Sopenharmony_ci#define MAX_CRASH_TIME 5
93569570cc8Sopenharmony_cistatic void WaitChildDied(pid_t pid)
93669570cc8Sopenharmony_ci{
93769570cc8Sopenharmony_ci    AppSpawningCtx *property = GetAppSpawningCtxByPid(pid);
93869570cc8Sopenharmony_ci    if (property != NULL && property->state == APP_STATE_SPAWNING) {
93969570cc8Sopenharmony_ci        APPSPAWN_LOGI("Child process %{public}s fail \'child crash \'pid %{public}d appId: %{public}d",
94069570cc8Sopenharmony_ci            GetProcessName(property), property->pid, property->client.id);
94169570cc8Sopenharmony_ci        if (property->client.id == g_lastDiedAppId + 1) {
94269570cc8Sopenharmony_ci            g_crashTimes++;
94369570cc8Sopenharmony_ci        } else {
94469570cc8Sopenharmony_ci            g_crashTimes = 1;
94569570cc8Sopenharmony_ci        }
94669570cc8Sopenharmony_ci        g_lastDiedAppId = property->client.id;
94769570cc8Sopenharmony_ci
94869570cc8Sopenharmony_ci        SendResponse(property->message->connection, &property->message->msgHeader, APPSPAWN_CHILD_CRASH, 0);
94969570cc8Sopenharmony_ci        DeleteAppSpawningCtx(property);
95069570cc8Sopenharmony_ci
95169570cc8Sopenharmony_ci        if (g_crashTimes >= MAX_CRASH_TIME) {
95269570cc8Sopenharmony_ci            APPSPAWN_LOGW("Continuous failures in spawning the app, restart appspawn");
95369570cc8Sopenharmony_ci            StopAppSpawn();
95469570cc8Sopenharmony_ci        }
95569570cc8Sopenharmony_ci    }
95669570cc8Sopenharmony_ci}
95769570cc8Sopenharmony_ci
95869570cc8Sopenharmony_cistatic void WaitChildTimeout(const TimerHandle taskHandle, void *context)
95969570cc8Sopenharmony_ci{
96069570cc8Sopenharmony_ci    AppSpawningCtx *property = (AppSpawningCtx *)context;
96169570cc8Sopenharmony_ci    APPSPAWN_LOGI("Child process %{public}s fail \'wait child timeout \'pid %{public}d appId: %{public}d",
96269570cc8Sopenharmony_ci        GetProcessName(property), property->pid, property->client.id);
96369570cc8Sopenharmony_ci    if (property->pid > 0) {
96469570cc8Sopenharmony_ci#if (!defined(CJAPP_SPAWN) && !defined(NATIVE_SPAWN))
96569570cc8Sopenharmony_ci        DumpSpawnStack(property->pid);
96669570cc8Sopenharmony_ci#endif
96769570cc8Sopenharmony_ci        kill(property->pid, SIGKILL);
96869570cc8Sopenharmony_ci    }
96969570cc8Sopenharmony_ci    SendResponse(property->message->connection, &property->message->msgHeader, APPSPAWN_SPAWN_TIMEOUT, 0);
97069570cc8Sopenharmony_ci    DeleteAppSpawningCtx(property);
97169570cc8Sopenharmony_ci}
97269570cc8Sopenharmony_ci
97369570cc8Sopenharmony_cistatic int ProcessChildFdCheck(int fd, AppSpawningCtx *property, int *pResult)
97469570cc8Sopenharmony_ci{
97569570cc8Sopenharmony_ci    int result = 0;
97669570cc8Sopenharmony_ci    (void)read(fd, &result, sizeof(result));
97769570cc8Sopenharmony_ci    APPSPAWN_LOGI("Child process %{public}s success pid %{public}d appId: %{public}d result: %{public}d",
97869570cc8Sopenharmony_ci        GetProcessName(property), property->pid, property->client.id, result);
97969570cc8Sopenharmony_ci    APPSPAWN_CHECK(property->message != NULL, return -1, "Invalid message in ctx %{public}d", property->client.id);
98069570cc8Sopenharmony_ci
98169570cc8Sopenharmony_ci    if (result != 0) {
98269570cc8Sopenharmony_ci        SendResponse(property->message->connection, &property->message->msgHeader, result, property->pid);
98369570cc8Sopenharmony_ci        DeleteAppSpawningCtx(property);
98469570cc8Sopenharmony_ci        return -1;
98569570cc8Sopenharmony_ci    }
98669570cc8Sopenharmony_ci    *pResult = result;
98769570cc8Sopenharmony_ci
98869570cc8Sopenharmony_ci    return 0;
98969570cc8Sopenharmony_ci}
99069570cc8Sopenharmony_ci
99169570cc8Sopenharmony_ci#define MSG_EXT_NAME_MAX_DECIMAL 10
99269570cc8Sopenharmony_ci#define MSG_EXT_NAME 1
99369570cc8Sopenharmony_cistatic void ProcessChildResponse(const WatcherHandle taskHandle, int fd, uint32_t *events, const void *context)
99469570cc8Sopenharmony_ci{
99569570cc8Sopenharmony_ci    AppSpawningCtx *property = (AppSpawningCtx *)context;
99669570cc8Sopenharmony_ci    property->forkCtx.watcherHandle = NULL;  // delete watcher
99769570cc8Sopenharmony_ci    LE_RemoveWatcher(LE_GetDefaultLoop(), (WatcherHandle)taskHandle);
99869570cc8Sopenharmony_ci
99969570cc8Sopenharmony_ci    int result = 0;
100069570cc8Sopenharmony_ci    if (ProcessChildFdCheck(fd, property, &result) != 0) {
100169570cc8Sopenharmony_ci        return;
100269570cc8Sopenharmony_ci    }
100369570cc8Sopenharmony_ci
100469570cc8Sopenharmony_ci    // success
100569570cc8Sopenharmony_ci    bool isDebuggable = CheckAppMsgFlagsSet(property, APP_FLAGS_DEBUGGABLE) == 1 ? true : false;
100669570cc8Sopenharmony_ci    AppSpawnedProcess *appInfo = AddSpawnedProcess(property->pid, GetBundleName(property), isDebuggable);
100769570cc8Sopenharmony_ci    uint32_t len = 0;
100869570cc8Sopenharmony_ci    char *pidMaxStr = NULL;
100969570cc8Sopenharmony_ci    pidMaxStr = GetAppPropertyExt(property, MSG_EXT_NAME_MAX_CHILD_PROCCESS_MAX, &len);
101069570cc8Sopenharmony_ci    uint32_t pidMax = 0;
101169570cc8Sopenharmony_ci    if (pidMaxStr != NULL && len != 0) {
101269570cc8Sopenharmony_ci        pidMax = strtoul(pidMaxStr, NULL, MSG_EXT_NAME_MAX_DECIMAL);
101369570cc8Sopenharmony_ci    }
101469570cc8Sopenharmony_ci#if MSG_EXT_NAME != 0
101569570cc8Sopenharmony_ci    pidMax = 0;
101669570cc8Sopenharmony_ci#endif
101769570cc8Sopenharmony_ci    if (appInfo) {
101869570cc8Sopenharmony_ci        AppSpawnMsgDacInfo *dacInfo = GetAppProperty(property, TLV_DAC_INFO);
101969570cc8Sopenharmony_ci        appInfo->uid = dacInfo != NULL ? dacInfo->uid : 0;
102069570cc8Sopenharmony_ci        appInfo->max = pidMax;
102169570cc8Sopenharmony_ci        appInfo->spawnStart.tv_sec = property->spawnStart.tv_sec;
102269570cc8Sopenharmony_ci        appInfo->spawnStart.tv_nsec = property->spawnStart.tv_nsec;
102369570cc8Sopenharmony_ci#ifdef DEBUG_BEGETCTL_BOOT
102469570cc8Sopenharmony_ci        if (IsDeveloperModeOpen()) {
102569570cc8Sopenharmony_ci            appInfo->message = property->message;
102669570cc8Sopenharmony_ci        }
102769570cc8Sopenharmony_ci#endif
102869570cc8Sopenharmony_ci        clock_gettime(CLOCK_MONOTONIC, &appInfo->spawnEnd);
102969570cc8Sopenharmony_ci        // add max info
103069570cc8Sopenharmony_ci    }
103169570cc8Sopenharmony_ci    WatchChildProcessFd(property);
103269570cc8Sopenharmony_ci    ProcessMgrHookExecute(STAGE_SERVER_APP_ADD, GetAppSpawnContent(), appInfo);
103369570cc8Sopenharmony_ci    // response
103469570cc8Sopenharmony_ci    AppSpawnHookExecute(STAGE_PARENT_PRE_RELY, 0, GetAppSpawnContent(), &property->client);
103569570cc8Sopenharmony_ci    SendResponse(property->message->connection, &property->message->msgHeader, result, property->pid);
103669570cc8Sopenharmony_ci    AppSpawnHookExecute(STAGE_PARENT_POST_RELY, 0, GetAppSpawnContent(), &property->client);
103769570cc8Sopenharmony_ci#ifdef DEBUG_BEGETCTL_BOOT
103869570cc8Sopenharmony_ci    if (IsDeveloperModeOpen()) {
103969570cc8Sopenharmony_ci        property->message = NULL;
104069570cc8Sopenharmony_ci    }
104169570cc8Sopenharmony_ci#endif
104269570cc8Sopenharmony_ci    DeleteAppSpawningCtx(property);
104369570cc8Sopenharmony_ci}
104469570cc8Sopenharmony_ci
104569570cc8Sopenharmony_cistatic void NotifyResToParent(AppSpawnContent *content, AppSpawnClient *client, int result)
104669570cc8Sopenharmony_ci{
104769570cc8Sopenharmony_ci    AppSpawningCtx *property = (AppSpawningCtx *)client;
104869570cc8Sopenharmony_ci    int fd = property->forkCtx.fd[1];
104969570cc8Sopenharmony_ci    if (fd >= 0) {
105069570cc8Sopenharmony_ci        (void)write(fd, &result, sizeof(result));
105169570cc8Sopenharmony_ci        (void)close(fd);
105269570cc8Sopenharmony_ci        property->forkCtx.fd[1] = -1;
105369570cc8Sopenharmony_ci    }
105469570cc8Sopenharmony_ci    APPSPAWN_LOGV("NotifyResToParent client id: %{public}u result: 0x%{public}x", client->id, result);
105569570cc8Sopenharmony_ci}
105669570cc8Sopenharmony_ci
105769570cc8Sopenharmony_cistatic int CreateAppSpawnServer(TaskHandle *server, const char *socketName)
105869570cc8Sopenharmony_ci{
105969570cc8Sopenharmony_ci    char path[128] = {0};  // 128 max path
106069570cc8Sopenharmony_ci    int ret = snprintf_s(path, sizeof(path), sizeof(path) - 1, "%s%s", APPSPAWN_SOCKET_DIR, socketName);
106169570cc8Sopenharmony_ci    APPSPAWN_CHECK(ret >= 0, return -1, "Failed to snprintf_s %{public}d", ret);
106269570cc8Sopenharmony_ci    int socketId = GetControlSocket(socketName);
106369570cc8Sopenharmony_ci    APPSPAWN_LOGI("get socket form env %{public}s socketId %{public}d", socketName, socketId);
106469570cc8Sopenharmony_ci
106569570cc8Sopenharmony_ci    LE_StreamServerInfo info = {};
106669570cc8Sopenharmony_ci    info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_SERVER;
106769570cc8Sopenharmony_ci    info.socketId = socketId;
106869570cc8Sopenharmony_ci    info.server = path;
106969570cc8Sopenharmony_ci    info.baseInfo.close = NULL;
107069570cc8Sopenharmony_ci    info.incommingConnect = OnConnection;
107169570cc8Sopenharmony_ci
107269570cc8Sopenharmony_ci    MakeDirRec(path, 0711, 0);  // 0711 default mask
107369570cc8Sopenharmony_ci    ret = LE_CreateStreamServer(LE_GetDefaultLoop(), server, &info);
107469570cc8Sopenharmony_ci    APPSPAWN_CHECK(ret == 0, return -1, "Failed to create socket for %{public}s errno: %{public}d", path, errno);
107569570cc8Sopenharmony_ci    SetFdCtrl(LE_GetSocketFd(*server), FD_CLOEXEC);
107669570cc8Sopenharmony_ci
107769570cc8Sopenharmony_ci    APPSPAWN_LOGI("CreateAppSpawnServer path %{public}s fd %{public}d", path, LE_GetSocketFd(*server));
107869570cc8Sopenharmony_ci    return 0;
107969570cc8Sopenharmony_ci}
108069570cc8Sopenharmony_ci
108169570cc8Sopenharmony_civoid AppSpawnDestroyContent(AppSpawnContent *content)
108269570cc8Sopenharmony_ci{
108369570cc8Sopenharmony_ci    if (content == NULL) {
108469570cc8Sopenharmony_ci        return;
108569570cc8Sopenharmony_ci    }
108669570cc8Sopenharmony_ci    if (content->parentToChildFd[0] > 0) {
108769570cc8Sopenharmony_ci        close(content->parentToChildFd[0]);
108869570cc8Sopenharmony_ci    }
108969570cc8Sopenharmony_ci    if (content->parentToChildFd[1] > 0) {
109069570cc8Sopenharmony_ci        close(content->parentToChildFd[1]);
109169570cc8Sopenharmony_ci    }
109269570cc8Sopenharmony_ci    AppSpawnMgr *appSpawnContent = (AppSpawnMgr *)content;
109369570cc8Sopenharmony_ci#ifdef USE_ENCAPS
109469570cc8Sopenharmony_ci    CloseDevEncaps(appSpawnContent->content.fdEncaps);
109569570cc8Sopenharmony_ci#endif
109669570cc8Sopenharmony_ci    if (appSpawnContent->sigHandler != NULL && appSpawnContent->servicePid == getpid()) {
109769570cc8Sopenharmony_ci        LE_CloseSignalTask(LE_GetDefaultLoop(), appSpawnContent->sigHandler);
109869570cc8Sopenharmony_ci    }
109969570cc8Sopenharmony_ci
110069570cc8Sopenharmony_ci    if (appSpawnContent->server != NULL && appSpawnContent->servicePid == getpid()) { // childProcess can't deal socket
110169570cc8Sopenharmony_ci        LE_CloseStreamTask(LE_GetDefaultLoop(), appSpawnContent->server);
110269570cc8Sopenharmony_ci        appSpawnContent->server = NULL;
110369570cc8Sopenharmony_ci    }
110469570cc8Sopenharmony_ci    LE_StopLoop(LE_GetDefaultLoop());
110569570cc8Sopenharmony_ci    LE_CloseLoop(LE_GetDefaultLoop());
110669570cc8Sopenharmony_ci    DeleteAppSpawnMgr(appSpawnContent);
110769570cc8Sopenharmony_ci}
110869570cc8Sopenharmony_ci
110969570cc8Sopenharmony_ciAPPSPAWN_STATIC int AppSpawnColdStartApp(struct AppSpawnContent *content, AppSpawnClient *client)
111069570cc8Sopenharmony_ci{
111169570cc8Sopenharmony_ci    AppSpawningCtx *property = (AppSpawningCtx *)client;
111269570cc8Sopenharmony_ci#ifdef CJAPP_SPAWN
111369570cc8Sopenharmony_ci    char *path = property->forkCtx.coldRunPath != NULL ? property->forkCtx.coldRunPath : "/system/bin/cjappspawn";
111469570cc8Sopenharmony_ci#elif NATIVE_SPAWN
111569570cc8Sopenharmony_ci    char *path = property->forkCtx.coldRunPath != NULL ? property->forkCtx.coldRunPath : "/system/bin/nativespawn";
111669570cc8Sopenharmony_ci#else
111769570cc8Sopenharmony_ci    char *path = property->forkCtx.coldRunPath != NULL ? property->forkCtx.coldRunPath : "/system/bin/appspawn";
111869570cc8Sopenharmony_ci#endif
111969570cc8Sopenharmony_ci    APPSPAWN_LOGI("ColdStartApp::processName: %{public}s path: %{public}s", GetProcessName(property), path);
112069570cc8Sopenharmony_ci
112169570cc8Sopenharmony_ci    // for cold run, use shared memory to exchange message
112269570cc8Sopenharmony_ci    APPSPAWN_LOGV("Write msg to child %{public}s", GetProcessName(property));
112369570cc8Sopenharmony_ci    int ret = WriteMsgToChild(property, IsNWebSpawnMode((AppSpawnMgr *)content));
112469570cc8Sopenharmony_ci    APPSPAWN_CHECK(ret == 0, return APPSPAWN_SYSTEM_ERROR, "Failed to write msg to child");
112569570cc8Sopenharmony_ci
112669570cc8Sopenharmony_ci    char buffer[4][32] = {0};  // 4 32 buffer for fd
112769570cc8Sopenharmony_ci    int len = sprintf_s(buffer[0], sizeof(buffer[0]), " %d ", property->forkCtx.fd[1]);
112869570cc8Sopenharmony_ci    APPSPAWN_CHECK(len > 0, return APPSPAWN_SYSTEM_ERROR, "Invalid to format fd");
112969570cc8Sopenharmony_ci    len = sprintf_s(buffer[1], sizeof(buffer[1]), " %u ", property->client.flags);
113069570cc8Sopenharmony_ci    APPSPAWN_CHECK(len > 0, return APPSPAWN_SYSTEM_ERROR, "Invalid to format flags");
113169570cc8Sopenharmony_ci    len = sprintf_s(buffer[2], sizeof(buffer[2]), " %u ", property->forkCtx.msgSize); // 2 2 index for dest path
113269570cc8Sopenharmony_ci    APPSPAWN_CHECK(len > 0, return APPSPAWN_SYSTEM_ERROR, "Invalid to format shmId ");
113369570cc8Sopenharmony_ci    len = sprintf_s(buffer[3], sizeof(buffer[3]), " %u ", property->client.id); // 3 3 index for client id
113469570cc8Sopenharmony_ci    APPSPAWN_CHECK(len > 0, return APPSPAWN_SYSTEM_ERROR, "Invalid to format shmId ");
113569570cc8Sopenharmony_ci
113669570cc8Sopenharmony_ci#ifndef APPSPAWN_TEST
113769570cc8Sopenharmony_ci    char *mode = IsNWebSpawnMode((AppSpawnMgr *)content) ? "nweb_cold" : "app_cold";
113869570cc8Sopenharmony_ci    // 2 2 index for dest path
113969570cc8Sopenharmony_ci    const char *const formatCmds[] = {
114069570cc8Sopenharmony_ci        path, "-mode", mode, "-fd", buffer[0], buffer[1], buffer[2],
114169570cc8Sopenharmony_ci        "-param", GetProcessName(property), buffer[3], NULL
114269570cc8Sopenharmony_ci    };
114369570cc8Sopenharmony_ci
114469570cc8Sopenharmony_ci    ret = execv(path, (char **)formatCmds);
114569570cc8Sopenharmony_ci    if (ret != 0) {
114669570cc8Sopenharmony_ci        APPSPAWN_LOGE("Failed to execv, errno: %{public}d", errno);
114769570cc8Sopenharmony_ci    }
114869570cc8Sopenharmony_ci#endif
114969570cc8Sopenharmony_ci    APPSPAWN_LOGV("ColdStartApp::processName: %{public}s end", GetProcessName(property));
115069570cc8Sopenharmony_ci    return 0;
115169570cc8Sopenharmony_ci}
115269570cc8Sopenharmony_ci
115369570cc8Sopenharmony_cistatic AppSpawningCtx *GetAppSpawningCtxFromArg(AppSpawnMgr *content, int argc, char *const argv[])
115469570cc8Sopenharmony_ci{
115569570cc8Sopenharmony_ci    AppSpawningCtx *property = CreateAppSpawningCtx();
115669570cc8Sopenharmony_ci    APPSPAWN_CHECK(property != NULL, return NULL, "Create app spawning ctx fail");
115769570cc8Sopenharmony_ci    property->forkCtx.fd[1] = atoi(argv[FD_VALUE_INDEX]);
115869570cc8Sopenharmony_ci    property->client.flags = (uint32_t)atoi(argv[FLAGS_VALUE_INDEX]);
115969570cc8Sopenharmony_ci    property->client.flags &= ~APP_COLD_START;
116069570cc8Sopenharmony_ci
116169570cc8Sopenharmony_ci    int isNweb = IsNWebSpawnMode(content);
116269570cc8Sopenharmony_ci    uint32_t size = (uint32_t)atoi(argv[SHM_SIZE_INDEX]);
116369570cc8Sopenharmony_ci    property->client.id = (uint32_t)atoi(argv[CLIENT_ID_INDEX]);
116469570cc8Sopenharmony_ci    uint8_t *buffer = (uint8_t *)GetMapMem(property->client.id,
116569570cc8Sopenharmony_ci        argv[PARAM_VALUE_INDEX], size, true, isNweb);
116669570cc8Sopenharmony_ci    if (buffer == NULL) {
116769570cc8Sopenharmony_ci        APPSPAWN_LOGE("Failed to map errno %{public}d %{public}s", property->client.id, argv[PARAM_VALUE_INDEX]);
116869570cc8Sopenharmony_ci        NotifyResToParent(&content->content, &property->client, APPSPAWN_SYSTEM_ERROR);
116969570cc8Sopenharmony_ci        DeleteAppSpawningCtx(property);
117069570cc8Sopenharmony_ci        return NULL;
117169570cc8Sopenharmony_ci    }
117269570cc8Sopenharmony_ci
117369570cc8Sopenharmony_ci    uint32_t msgRecvLen = 0;
117469570cc8Sopenharmony_ci    uint32_t remainLen = 0;
117569570cc8Sopenharmony_ci    AppSpawnMsgNode *message = NULL;
117669570cc8Sopenharmony_ci    int ret = GetAppSpawnMsgFromBuffer(buffer, ((AppSpawnMsg *)buffer)->msgLen, &message, &msgRecvLen, &remainLen);
117769570cc8Sopenharmony_ci    // release map
117869570cc8Sopenharmony_ci    munmap((char *)buffer, size);
117969570cc8Sopenharmony_ci    //unlink
118069570cc8Sopenharmony_ci    char path[PATH_MAX] = {0};
118169570cc8Sopenharmony_ci    int len = sprintf_s(path, sizeof(path), APPSPAWN_MSG_DIR "%s/%s_%u",
118269570cc8Sopenharmony_ci        isNweb ? "nwebspawn" : "appspawn", argv[PARAM_VALUE_INDEX], property->client.id);
118369570cc8Sopenharmony_ci    if (len > 0) {
118469570cc8Sopenharmony_ci        unlink(path);
118569570cc8Sopenharmony_ci    }
118669570cc8Sopenharmony_ci
118769570cc8Sopenharmony_ci    if (ret == 0 && DecodeAppSpawnMsg(message) == 0 && CheckAppSpawnMsg(message) == 0) {
118869570cc8Sopenharmony_ci        property->message = message;
118969570cc8Sopenharmony_ci        message = NULL;
119069570cc8Sopenharmony_ci        return property;
119169570cc8Sopenharmony_ci    }
119269570cc8Sopenharmony_ci    NotifyResToParent(&content->content, &property->client, APPSPAWN_MSG_INVALID);
119369570cc8Sopenharmony_ci    DeleteAppSpawnMsg(message);
119469570cc8Sopenharmony_ci    DeleteAppSpawningCtx(property);
119569570cc8Sopenharmony_ci    return NULL;
119669570cc8Sopenharmony_ci}
119769570cc8Sopenharmony_ci
119869570cc8Sopenharmony_cistatic void AppSpawnColdRun(AppSpawnContent *content, int argc, char *const argv[])
119969570cc8Sopenharmony_ci{
120069570cc8Sopenharmony_ci    APPSPAWN_CHECK(argc >= ARG_NULL, return, "Invalid arg for cold start %{public}d", argc);
120169570cc8Sopenharmony_ci    AppSpawnMgr *appSpawnContent = (AppSpawnMgr *)content;
120269570cc8Sopenharmony_ci    APPSPAWN_CHECK(appSpawnContent != NULL, return, "Invalid appspawn content");
120369570cc8Sopenharmony_ci
120469570cc8Sopenharmony_ci    AppSpawningCtx *property = GetAppSpawningCtxFromArg(appSpawnContent, argc, argv);
120569570cc8Sopenharmony_ci    if (property == NULL) {
120669570cc8Sopenharmony_ci        APPSPAWN_LOGE("Failed to get property from arg");
120769570cc8Sopenharmony_ci        return;
120869570cc8Sopenharmony_ci    }
120969570cc8Sopenharmony_ci    DumpAppSpawnMsg(property->message);
121069570cc8Sopenharmony_ci
121169570cc8Sopenharmony_ci    int ret = AppSpawnExecuteSpawningHook(content, &property->client);
121269570cc8Sopenharmony_ci    if (ret == 0) {
121369570cc8Sopenharmony_ci        ret = AppSpawnExecutePreReplyHook(content, &property->client);
121469570cc8Sopenharmony_ci        // success
121569570cc8Sopenharmony_ci        NotifyResToParent(content, &property->client, ret);
121669570cc8Sopenharmony_ci
121769570cc8Sopenharmony_ci        (void)AppSpawnExecutePostReplyHook(content, &property->client);
121869570cc8Sopenharmony_ci
121969570cc8Sopenharmony_ci        ret = APPSPAWN_SYSTEM_ERROR;
122069570cc8Sopenharmony_ci        if (content->runChildProcessor != NULL) {
122169570cc8Sopenharmony_ci            ret = content->runChildProcessor(content, &property->client);
122269570cc8Sopenharmony_ci        }
122369570cc8Sopenharmony_ci    } else {
122469570cc8Sopenharmony_ci        NotifyResToParent(content, &property->client, ret);
122569570cc8Sopenharmony_ci    }
122669570cc8Sopenharmony_ci
122769570cc8Sopenharmony_ci    if (ret != 0) {
122869570cc8Sopenharmony_ci        AppSpawnEnvClear(content, &property->client);
122969570cc8Sopenharmony_ci    }
123069570cc8Sopenharmony_ci    APPSPAWN_LOGI("AppSpawnColdRun exit %{public}d.", getpid());
123169570cc8Sopenharmony_ci}
123269570cc8Sopenharmony_ci
123369570cc8Sopenharmony_cistatic void AppSpawnRun(AppSpawnContent *content, int argc, char *const argv[])
123469570cc8Sopenharmony_ci{
123569570cc8Sopenharmony_ci    APPSPAWN_LOGI("AppSpawnRun");
123669570cc8Sopenharmony_ci    AppSpawnMgr *appSpawnContent = (AppSpawnMgr *)content;
123769570cc8Sopenharmony_ci    APPSPAWN_CHECK(appSpawnContent != NULL, return, "Invalid appspawn content");
123869570cc8Sopenharmony_ci
123969570cc8Sopenharmony_ci    LE_STATUS status = LE_CreateSignalTask(LE_GetDefaultLoop(), &appSpawnContent->sigHandler, ProcessSignal);
124069570cc8Sopenharmony_ci    if (status == 0) {
124169570cc8Sopenharmony_ci        (void)LE_AddSignal(LE_GetDefaultLoop(), appSpawnContent->sigHandler, SIGCHLD);
124269570cc8Sopenharmony_ci        (void)LE_AddSignal(LE_GetDefaultLoop(), appSpawnContent->sigHandler, SIGTERM);
124369570cc8Sopenharmony_ci    }
124469570cc8Sopenharmony_ci
124569570cc8Sopenharmony_ci#ifdef USE_ENCAPS
124669570cc8Sopenharmony_ci    appSpawnContent->content.fdEncaps = OpenDevEncaps();
124769570cc8Sopenharmony_ci#endif
124869570cc8Sopenharmony_ci    LE_RunLoop(LE_GetDefaultLoop());
124969570cc8Sopenharmony_ci    APPSPAWN_LOGI("AppSpawnRun exit mode: %{public}d ", content->mode);
125069570cc8Sopenharmony_ci
125169570cc8Sopenharmony_ci    (void)ServerStageHookExecute(STAGE_SERVER_EXIT, content); // service exit,plugin can deal task
125269570cc8Sopenharmony_ci    AppSpawnDestroyContent(content);
125369570cc8Sopenharmony_ci}
125469570cc8Sopenharmony_ci
125569570cc8Sopenharmony_ciAPPSPAWN_STATIC int AppSpawnClearEnv(AppSpawnMgr *content, AppSpawningCtx *property)
125669570cc8Sopenharmony_ci{
125769570cc8Sopenharmony_ci    APPSPAWN_CHECK(content != NULL, return 0, "Invalid appspawn content");
125869570cc8Sopenharmony_ci    DeleteAppSpawningCtx(property);
125969570cc8Sopenharmony_ci    AppSpawnDestroyContent(&content->content);
126069570cc8Sopenharmony_ci    APPSPAWN_LOGV("clear %{public}d end", getpid());
126169570cc8Sopenharmony_ci    return 0;
126269570cc8Sopenharmony_ci}
126369570cc8Sopenharmony_ci
126469570cc8Sopenharmony_cistatic int IsEnablePerfork()
126569570cc8Sopenharmony_ci{
126669570cc8Sopenharmony_ci    char buffer[32] = {0};
126769570cc8Sopenharmony_ci    int ret = GetParameter("persist.sys.prefork.enable", "true", buffer, sizeof(buffer));
126869570cc8Sopenharmony_ci    APPSPAWN_LOGV("IsEnablePerfork result %{public}d, %{public}s", ret, buffer);
126969570cc8Sopenharmony_ci    return strcmp(buffer, "true") == 0;
127069570cc8Sopenharmony_ci}
127169570cc8Sopenharmony_ci
127269570cc8Sopenharmony_ciAppSpawnContent *AppSpawnCreateContent(const char *socketName, char *longProcName, uint32_t nameLen, int mode)
127369570cc8Sopenharmony_ci{
127469570cc8Sopenharmony_ci    APPSPAWN_CHECK(socketName != NULL && longProcName != NULL, return NULL, "Invalid name");
127569570cc8Sopenharmony_ci    APPSPAWN_LOGI("AppSpawnCreateContent %{public}s %{public}u mode %{public}d", socketName, nameLen, mode);
127669570cc8Sopenharmony_ci
127769570cc8Sopenharmony_ci    AppSpawnMgr *appSpawnContent = CreateAppSpawnMgr(mode);
127869570cc8Sopenharmony_ci    APPSPAWN_CHECK(appSpawnContent != NULL, return NULL, "Failed to alloc memory for appspawn");
127969570cc8Sopenharmony_ci    appSpawnContent->content.longProcName = longProcName;
128069570cc8Sopenharmony_ci    appSpawnContent->content.longProcNameLen = nameLen;
128169570cc8Sopenharmony_ci    appSpawnContent->content.notifyResToParent = NotifyResToParent;
128269570cc8Sopenharmony_ci    if (IsColdRunMode(appSpawnContent)) {
128369570cc8Sopenharmony_ci        appSpawnContent->content.runAppSpawn = AppSpawnColdRun;
128469570cc8Sopenharmony_ci    } else {
128569570cc8Sopenharmony_ci        appSpawnContent->content.runAppSpawn = AppSpawnRun;
128669570cc8Sopenharmony_ci        appSpawnContent->content.coldStartApp = AppSpawnColdStartApp;
128769570cc8Sopenharmony_ci
128869570cc8Sopenharmony_ci        int ret = CreateAppSpawnServer(&appSpawnContent->server, socketName);
128969570cc8Sopenharmony_ci        APPSPAWN_CHECK(ret == 0, AppSpawnDestroyContent(&appSpawnContent->content);
129069570cc8Sopenharmony_ci            return NULL, "Failed to create server");
129169570cc8Sopenharmony_ci    }
129269570cc8Sopenharmony_ci    appSpawnContent->content.enablePerfork = IsEnablePerfork();
129369570cc8Sopenharmony_ci    return &appSpawnContent->content;
129469570cc8Sopenharmony_ci}
129569570cc8Sopenharmony_ci
129669570cc8Sopenharmony_ciAppSpawnContent *StartSpawnService(const AppSpawnStartArg *startArg, uint32_t argvSize, int argc, char *const argv[])
129769570cc8Sopenharmony_ci{
129869570cc8Sopenharmony_ci    APPSPAWN_CHECK(startArg != NULL && argv != NULL, return NULL, "Invalid start arg");
129969570cc8Sopenharmony_ci    pid_t pid = 0;
130069570cc8Sopenharmony_ci    AppSpawnStartArg *arg = (AppSpawnStartArg *)startArg;
130169570cc8Sopenharmony_ci    APPSPAWN_LOGV("Start appspawn argvSize %{public}d mode %{public}d service %{public}s",
130269570cc8Sopenharmony_ci        argvSize, arg->mode, arg->serviceName);
130369570cc8Sopenharmony_ci    if (arg->mode == MODE_FOR_APP_SPAWN) {
130469570cc8Sopenharmony_ci#ifndef APPSPAWN_TEST
130569570cc8Sopenharmony_ci        pid = NWebSpawnLaunch();
130669570cc8Sopenharmony_ci        if (pid == 0) {
130769570cc8Sopenharmony_ci            arg->socketName = NWEBSPAWN_SOCKET_NAME;
130869570cc8Sopenharmony_ci            arg->serviceName = NWEBSPAWN_SERVER_NAME;
130969570cc8Sopenharmony_ci            arg->moduleType = MODULE_NWEBSPAWN;
131069570cc8Sopenharmony_ci            arg->mode = MODE_FOR_NWEB_SPAWN;
131169570cc8Sopenharmony_ci            arg->initArg = 1;
131269570cc8Sopenharmony_ci        }
131369570cc8Sopenharmony_ci#endif
131469570cc8Sopenharmony_ci    } else if (arg->mode == MODE_FOR_NWEB_SPAWN && getuid() == 0) {
131569570cc8Sopenharmony_ci        NWebSpawnInit();
131669570cc8Sopenharmony_ci    }
131769570cc8Sopenharmony_ci    if (arg->initArg) {
131869570cc8Sopenharmony_ci        int ret = memset_s(argv[0], argvSize, 0, (size_t)argvSize);
131969570cc8Sopenharmony_ci        APPSPAWN_CHECK(ret == EOK, return NULL, "Failed to memset argv[0]");
132069570cc8Sopenharmony_ci        ret = strncpy_s(argv[0], argvSize, arg->serviceName, strlen(arg->serviceName));
132169570cc8Sopenharmony_ci        APPSPAWN_CHECK(ret == EOK, return NULL, "Failed to copy service name %{public}s", arg->serviceName);
132269570cc8Sopenharmony_ci    }
132369570cc8Sopenharmony_ci
132469570cc8Sopenharmony_ci    // load module appspawn/common
132569570cc8Sopenharmony_ci    AppSpawnLoadAutoRunModules(MODULE_COMMON);
132669570cc8Sopenharmony_ci    AppSpawnModuleMgrInstall(ASAN_MODULE_PATH);
132769570cc8Sopenharmony_ci
132869570cc8Sopenharmony_ci    APPSPAWN_CHECK(LE_GetDefaultLoop() != NULL, return NULL, "Invalid default loop");
132969570cc8Sopenharmony_ci    AppSpawnContent *content = AppSpawnCreateContent(arg->socketName, argv[0], argvSize, arg->mode);
133069570cc8Sopenharmony_ci    APPSPAWN_CHECK(content != NULL, return NULL, "Failed to create content for %{public}s", arg->socketName);
133169570cc8Sopenharmony_ci
133269570cc8Sopenharmony_ci    AppSpawnLoadAutoRunModules(arg->moduleType);  // load corresponding plugin according to startup mode
133369570cc8Sopenharmony_ci    int ret = ServerStageHookExecute(STAGE_SERVER_PRELOAD, content);   // Preload, prase the sandbox
133469570cc8Sopenharmony_ci    APPSPAWN_CHECK(ret == 0, AppSpawnDestroyContent(content);
133569570cc8Sopenharmony_ci        return NULL, "Failed to prepare load %{public}s result: %{public}d", arg->serviceName, ret);
133669570cc8Sopenharmony_ci#ifndef APPSPAWN_TEST
133769570cc8Sopenharmony_ci    APPSPAWN_CHECK(content->runChildProcessor != NULL, AppSpawnDestroyContent(content);
133869570cc8Sopenharmony_ci        return NULL, "No child processor %{public}s result: %{public}d", arg->serviceName, ret);
133969570cc8Sopenharmony_ci#endif
134069570cc8Sopenharmony_ci    AddAppSpawnHook(STAGE_CHILD_PRE_RUN, HOOK_PRIO_LOWEST, AppSpawnClearEnv);
134169570cc8Sopenharmony_ci    if (arg->mode == MODE_FOR_APP_SPAWN) {
134269570cc8Sopenharmony_ci        AddSpawnedProcess(pid, NWEBSPAWN_SERVER_NAME, false);
134369570cc8Sopenharmony_ci        SetParameter("bootevent.appspawn.started", "true");
134469570cc8Sopenharmony_ci    }
134569570cc8Sopenharmony_ci    return content;
134669570cc8Sopenharmony_ci}
134769570cc8Sopenharmony_ci
134869570cc8Sopenharmony_cistatic AppSpawnMsgNode *ProcessSpawnBegetctlMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message)
134969570cc8Sopenharmony_ci{
135069570cc8Sopenharmony_ci    uint32_t len = 0;
135169570cc8Sopenharmony_ci    const char *cmdMsg = (const char *)GetAppSpawnMsgExtInfo(message, MSG_EXT_NAME_BEGET_PID, &len);
135269570cc8Sopenharmony_ci    APPSPAWN_CHECK(cmdMsg != NULL, return NULL, "Failed to get extInfo");
135369570cc8Sopenharmony_ci    AppSpawnedProcess *appInfo = GetSpawnedProcess(atoi(cmdMsg));
135469570cc8Sopenharmony_ci    APPSPAWN_CHECK(appInfo != NULL, return NULL, "Failed to get app info");
135569570cc8Sopenharmony_ci    AppSpawnMsgNode *msgNode = RebuildAppSpawnMsgNode(message, appInfo);
135669570cc8Sopenharmony_ci    APPSPAWN_CHECK(msgNode != NULL, return NULL, "Failed to rebuild app message node");
135769570cc8Sopenharmony_ci    int ret = DecodeAppSpawnMsg(msgNode);
135869570cc8Sopenharmony_ci    if (ret != 0) {
135969570cc8Sopenharmony_ci        DeleteAppSpawnMsg(msgNode);
136069570cc8Sopenharmony_ci        return NULL;
136169570cc8Sopenharmony_ci    }
136269570cc8Sopenharmony_ci    return msgNode;
136369570cc8Sopenharmony_ci}
136469570cc8Sopenharmony_ci
136569570cc8Sopenharmony_cistatic void ProcessBegetCmdMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message)
136669570cc8Sopenharmony_ci{
136769570cc8Sopenharmony_ci    AppSpawnMsg *msg = &message->msgHeader;
136869570cc8Sopenharmony_ci    if (!IsDeveloperModeOpen()) {
136969570cc8Sopenharmony_ci        SendResponse(connection, msg, APPSPAWN_DEBUG_MODE_NOT_SUPPORT, 0);
137069570cc8Sopenharmony_ci        DeleteAppSpawnMsg(message);
137169570cc8Sopenharmony_ci        return;
137269570cc8Sopenharmony_ci    }
137369570cc8Sopenharmony_ci    AppSpawnMsgNode *msgNode = ProcessSpawnBegetctlMsg(connection, message);
137469570cc8Sopenharmony_ci    if (msgNode == NULL) {
137569570cc8Sopenharmony_ci        SendResponse(connection, msg, APPSPAWN_DEBUG_MODE_NOT_SUPPORT, 0);
137669570cc8Sopenharmony_ci        DeleteAppSpawnMsg(message);
137769570cc8Sopenharmony_ci        return;
137869570cc8Sopenharmony_ci    }
137969570cc8Sopenharmony_ci    ProcessSpawnReqMsg(connection, msgNode);
138069570cc8Sopenharmony_ci    DeleteAppSpawnMsg(message);
138169570cc8Sopenharmony_ci    DeleteAppSpawnMsg(msgNode);
138269570cc8Sopenharmony_ci}
138369570cc8Sopenharmony_ci
138469570cc8Sopenharmony_cistatic int GetArkWebInstallPath(const char *key, char *value)
138569570cc8Sopenharmony_ci{
138669570cc8Sopenharmony_ci    int len = GetParameter(key, "", value, PATH_SIZE);
138769570cc8Sopenharmony_ci    APPSPAWN_CHECK(len > 0, return -1, "Failed to get arkwebcore install path from param, len %{public}d", len);
138869570cc8Sopenharmony_ci    for (int i = len - 1; i >= 0; i--) {
138969570cc8Sopenharmony_ci        if (value[i] == '/') {
139069570cc8Sopenharmony_ci            value[i] = '\0';
139169570cc8Sopenharmony_ci            return i;
139269570cc8Sopenharmony_ci        }
139369570cc8Sopenharmony_ci        value[i] = '\0';
139469570cc8Sopenharmony_ci    }
139569570cc8Sopenharmony_ci    return -1;
139669570cc8Sopenharmony_ci}
139769570cc8Sopenharmony_ci
139869570cc8Sopenharmony_cistatic bool CheckAllDigit(char *userId)
139969570cc8Sopenharmony_ci{
140069570cc8Sopenharmony_ci    for (int i = 0; userId[i] != '\0'; i++) {
140169570cc8Sopenharmony_ci        if (!isdigit(userId[i])) {
140269570cc8Sopenharmony_ci            return false;
140369570cc8Sopenharmony_ci        }
140469570cc8Sopenharmony_ci    }
140569570cc8Sopenharmony_ci    return true;
140669570cc8Sopenharmony_ci}
140769570cc8Sopenharmony_ci
140869570cc8Sopenharmony_ci#ifdef APPSPAWN_SANDBOX_NEW
140969570cc8Sopenharmony_cistatic int ProcessSpawnRemountMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message)
141069570cc8Sopenharmony_ci{
141169570cc8Sopenharmony_ci    char srcPath[PATH_SIZE] = {0};
141269570cc8Sopenharmony_ci    int len = GetArkWebInstallPath("persist.arkwebcore.install_path", srcPath);
141369570cc8Sopenharmony_ci    APPSPAWN_CHECK(len > 0, return -1, "Failed to get arkwebcore install path");
141469570cc8Sopenharmony_ci
141569570cc8Sopenharmony_ci    char *rootPath = "/mnt/sandbox";
141669570cc8Sopenharmony_ci    DIR *rootDir = opendir(rootPath);
141769570cc8Sopenharmony_ci    APPSPAWN_CHECK(rootDir != NULL, return -1, "Failed to opendir %{public}s, errno %{public}d", rootPath, errno);
141869570cc8Sopenharmony_ci
141969570cc8Sopenharmony_ci    struct dirent *ent;
142069570cc8Sopenharmony_ci    while ((ent = readdir(rootDir)) != NULL) {
142169570cc8Sopenharmony_ci        char *userId = ent->d_name;
142269570cc8Sopenharmony_ci        if (strcmp(userId, ".") == 0 || strcmp(userId, "..") == 0 || !CheckAllDigit(userId)) {
142369570cc8Sopenharmony_ci            continue;
142469570cc8Sopenharmony_ci        }
142569570cc8Sopenharmony_ci        char destPath[PATH_SIZE] = {0};
142669570cc8Sopenharmony_ci        int ret = snprintf_s(destPath, sizeof(destPath), sizeof(destPath) - 1,
142769570cc8Sopenharmony_ci            "%s/%s/app-root/mnt/nweb/tmp", rootPath, userId);
142869570cc8Sopenharmony_ci        APPSPAWN_CHECK(ret > 0, continue, "Failed to snprintf_s, errno %{public}d", errno);
142969570cc8Sopenharmony_ci
143069570cc8Sopenharmony_ci        ret = umount2(destPath, MNT_DETACH);
143169570cc8Sopenharmony_ci        if (ret != 0) {
143269570cc8Sopenharmony_ci            APPSPAWN_LOGW("Umount %{public}s failed, errno %{public}d", destPath, errno);
143369570cc8Sopenharmony_ci        }
143469570cc8Sopenharmony_ci
143569570cc8Sopenharmony_ci        ret = mount(srcPath, destPath, NULL, MS_BIND | MS_REC, NULL);
143669570cc8Sopenharmony_ci        if (ret != 0 && errno == EBUSY) {
143769570cc8Sopenharmony_ci            ret = mount(srcPath, destPath, NULL, MS_BIND | MS_REC, NULL);
143869570cc8Sopenharmony_ci            APPSPAWN_LOGW("Bind mount again %{public}s to %{public}s, ret %{public}d", srcPath, destPath, ret);
143969570cc8Sopenharmony_ci        }
144069570cc8Sopenharmony_ci        APPSPAWN_CHECK(ret == 0, continue,
144169570cc8Sopenharmony_ci            "Failed to bind mount %{public}s to %{public}s, errno %{public}d", srcPath, destPath, errno);
144269570cc8Sopenharmony_ci
144369570cc8Sopenharmony_ci        ret = mount(NULL, destPath, NULL, MS_SHARED, NULL);
144469570cc8Sopenharmony_ci        APPSPAWN_CHECK(ret == 0, continue,
144569570cc8Sopenharmony_ci            "Failed to shared mount %{public}s, errno %{public}d", destPath, errno);
144669570cc8Sopenharmony_ci
144769570cc8Sopenharmony_ci        APPSPAWN_LOGI("Remount %{public}s to %{public}s success", srcPath, destPath);
144869570cc8Sopenharmony_ci    }
144969570cc8Sopenharmony_ci    closedir(rootDir);
145069570cc8Sopenharmony_ci    return 0;
145169570cc8Sopenharmony_ci}
145269570cc8Sopenharmony_ci#else
145369570cc8Sopenharmony_cistatic int ProcessSpawnRemountMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message)
145469570cc8Sopenharmony_ci{
145569570cc8Sopenharmony_ci    char srcPath[PATH_SIZE] = {0};
145669570cc8Sopenharmony_ci    int len = GetArkWebInstallPath("persist.arkwebcore.install_path", srcPath);
145769570cc8Sopenharmony_ci    APPSPAWN_CHECK(len > 0, return -1, "Failed to get arkwebcore install path");
145869570cc8Sopenharmony_ci
145969570cc8Sopenharmony_ci    char *rootPath = "/mnt/sandbox";
146069570cc8Sopenharmony_ci    DIR *rootDir = opendir(rootPath);
146169570cc8Sopenharmony_ci    APPSPAWN_CHECK(rootDir != NULL, return -1, "Failed to opendir %{public}s, errno %{public}d", rootPath, errno);
146269570cc8Sopenharmony_ci
146369570cc8Sopenharmony_ci    struct dirent *ent;
146469570cc8Sopenharmony_ci    while ((ent = readdir(rootDir)) != NULL) {
146569570cc8Sopenharmony_ci        char *userId = ent->d_name;
146669570cc8Sopenharmony_ci        if (strcmp(userId, ".") == 0 || strcmp(userId, "..") == 0 || !CheckAllDigit(userId)) {
146769570cc8Sopenharmony_ci            continue;
146869570cc8Sopenharmony_ci        }
146969570cc8Sopenharmony_ci
147069570cc8Sopenharmony_ci        char userIdPath[PATH_SIZE] = {0};
147169570cc8Sopenharmony_ci        int ret = snprintf_s(userIdPath, sizeof(userIdPath), sizeof(userIdPath) - 1, "%s/%s", rootPath, userId);
147269570cc8Sopenharmony_ci        APPSPAWN_CHECK(ret > 0, continue, "Failed to snprintf_s, errno %{public}d", errno);
147369570cc8Sopenharmony_ci
147469570cc8Sopenharmony_ci        DIR *userIdDir = opendir(userIdPath);
147569570cc8Sopenharmony_ci        APPSPAWN_CHECK(userIdDir != NULL, continue, "Failed to open %{public}s, errno %{public}d", userIdPath, errno);
147669570cc8Sopenharmony_ci
147769570cc8Sopenharmony_ci        while ((ent = readdir(userIdDir)) != NULL) {
147869570cc8Sopenharmony_ci            char *bundleName = ent->d_name;
147969570cc8Sopenharmony_ci            if (strcmp(bundleName, ".") == 0 || strcmp(bundleName, "..") == 0) {
148069570cc8Sopenharmony_ci                continue;
148169570cc8Sopenharmony_ci            }
148269570cc8Sopenharmony_ci            char destPath[PATH_SIZE] = {0};
148369570cc8Sopenharmony_ci            ret = snprintf_s(destPath, sizeof(destPath), sizeof(destPath) - 1,
148469570cc8Sopenharmony_ci                "%s/%s/data/storage/el1/bundle/arkwebcore", userIdPath, bundleName);
148569570cc8Sopenharmony_ci            APPSPAWN_CHECK(ret > 0, continue, "Failed to snprintf_s, errno %{public}d", errno);
148669570cc8Sopenharmony_ci
148769570cc8Sopenharmony_ci            umount2(destPath, MNT_DETACH);
148869570cc8Sopenharmony_ci            ret = mount(srcPath, destPath, NULL, MS_BIND | MS_REC, NULL);
148969570cc8Sopenharmony_ci            if (ret != 0 && errno == EBUSY) {
149069570cc8Sopenharmony_ci                ret = mount(srcPath, destPath, NULL, MS_BIND | MS_REC, NULL);
149169570cc8Sopenharmony_ci                APPSPAWN_LOGV("mount again %{public}s to %{public}s, ret %{public}d", srcPath, destPath, ret);
149269570cc8Sopenharmony_ci            }
149369570cc8Sopenharmony_ci            APPSPAWN_CHECK(ret == 0, continue,
149469570cc8Sopenharmony_ci                "Failed to bind mount %{public}s to %{public}s, errno %{public}d", srcPath, destPath, errno);
149569570cc8Sopenharmony_ci
149669570cc8Sopenharmony_ci            ret = mount(NULL, destPath, NULL, MS_SHARED, NULL);
149769570cc8Sopenharmony_ci            APPSPAWN_CHECK(ret == 0, continue,
149869570cc8Sopenharmony_ci                "Failed to shared mount %{public}s to %{public}s, errno %{public}d", srcPath, destPath, errno);
149969570cc8Sopenharmony_ci
150069570cc8Sopenharmony_ci            APPSPAWN_LOGV("Remount %{public}s to %{public}s success", srcPath, destPath);
150169570cc8Sopenharmony_ci        }
150269570cc8Sopenharmony_ci        closedir(userIdDir);
150369570cc8Sopenharmony_ci    }
150469570cc8Sopenharmony_ci    closedir(rootDir);
150569570cc8Sopenharmony_ci    return 0;
150669570cc8Sopenharmony_ci}
150769570cc8Sopenharmony_ci#endif
150869570cc8Sopenharmony_ci
150969570cc8Sopenharmony_cistatic void ProcessSpawnRestartMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message)
151069570cc8Sopenharmony_ci{
151169570cc8Sopenharmony_ci    AppSpawnContent *content = GetAppSpawnContent();
151269570cc8Sopenharmony_ci    if (!IsNWebSpawnMode((AppSpawnMgr *)content)) {
151369570cc8Sopenharmony_ci        SendResponse(connection, &message->msgHeader, APPSPAWN_MSG_INVALID, 0);
151469570cc8Sopenharmony_ci        DeleteAppSpawnMsg(message);
151569570cc8Sopenharmony_ci        APPSPAWN_LOGE("Restart msg only support nwebspawn");
151669570cc8Sopenharmony_ci        return;
151769570cc8Sopenharmony_ci    }
151869570cc8Sopenharmony_ci
151969570cc8Sopenharmony_ci    TraversalSpawnedProcess(AppQueueDestroyProc, NULL);
152069570cc8Sopenharmony_ci    SendResponse(connection, &message->msgHeader, 0, 0);
152169570cc8Sopenharmony_ci    DeleteAppSpawnMsg(message);
152269570cc8Sopenharmony_ci    (void) ServerStageHookExecute(STAGE_SERVER_EXIT, content);
152369570cc8Sopenharmony_ci
152469570cc8Sopenharmony_ci    errno = 0;
152569570cc8Sopenharmony_ci    int fd = GetControlSocket(NWEBSPAWN_SOCKET_NAME);
152669570cc8Sopenharmony_ci    APPSPAWN_CHECK(fd >= 0, return, "Get fd failed %{public}d, errno %{public}d", fd, errno);
152769570cc8Sopenharmony_ci
152869570cc8Sopenharmony_ci    int op = fcntl(fd, F_GETFD);
152969570cc8Sopenharmony_ci    int ret = fcntl(fd, F_SETFD, (unsigned int)op & ~FD_CLOEXEC);
153069570cc8Sopenharmony_ci    if (ret < 0) {
153169570cc8Sopenharmony_ci        APPSPAWN_LOGE("Set fd failed %{public}d, %{public}d, ret %{public}d, errno %{public}d", fd, op, ret, errno);
153269570cc8Sopenharmony_ci    }
153369570cc8Sopenharmony_ci
153469570cc8Sopenharmony_ci    char *path = "/system/bin/appspawn";
153569570cc8Sopenharmony_ci    char *mode = NWEBSPAWN_RESTART;
153669570cc8Sopenharmony_ci    const char *const formatCmds[] = {path, "-mode", mode, NULL};
153769570cc8Sopenharmony_ci    ret = execv(path, (char **)formatCmds);
153869570cc8Sopenharmony_ci    APPSPAWN_LOGE("Failed to execv, ret %{public}d, errno %{public}d", ret, errno);
153969570cc8Sopenharmony_ci}
154069570cc8Sopenharmony_ci
154169570cc8Sopenharmony_ciAPPSPAWN_STATIC int AppspawpnDevicedebugKill(int pid, cJSON *args)
154269570cc8Sopenharmony_ci{
154369570cc8Sopenharmony_ci    cJSON *signal = cJSON_GetObjectItem(args, "signal");
154469570cc8Sopenharmony_ci    if (!cJSON_IsNumber(signal)) {
154569570cc8Sopenharmony_ci        APPSPAWN_LOGE("appspawn devicedebug json get signal fail");
154669570cc8Sopenharmony_ci        return -1;
154769570cc8Sopenharmony_ci    }
154869570cc8Sopenharmony_ci
154969570cc8Sopenharmony_ci    AppSpawnedProcess *appInfo = GetSpawnedProcess(pid);
155069570cc8Sopenharmony_ci    if (appInfo == NULL) {
155169570cc8Sopenharmony_ci        APPSPAWN_LOGE("appspawn devicedebug get app info unsuccess, pid=%{public}d", pid);
155269570cc8Sopenharmony_ci        return -1;
155369570cc8Sopenharmony_ci    }
155469570cc8Sopenharmony_ci
155569570cc8Sopenharmony_ci    if (!appInfo->isDebuggable) {
155669570cc8Sopenharmony_ci        APPSPAWN_LOGE("appspawn devicedebug process is not debuggable, pid=%{public}d", pid);
155769570cc8Sopenharmony_ci        return -1;
155869570cc8Sopenharmony_ci    }
155969570cc8Sopenharmony_ci
156069570cc8Sopenharmony_ci    APPSPAWN_LOGI("appspawn devicedebug debugable=%{public}d, pid=%{public}d, signal=%{public}d",
156169570cc8Sopenharmony_ci        appInfo->isDebuggable, pid, signal->valueint);
156269570cc8Sopenharmony_ci
156369570cc8Sopenharmony_ci    if (kill(pid, signal->valueint) != 0) {
156469570cc8Sopenharmony_ci        APPSPAWN_LOGE("appspawn devicedebug unable to kill process, pid: %{public}d ret %{public}d", pid, errno);
156569570cc8Sopenharmony_ci        return -1;
156669570cc8Sopenharmony_ci    }
156769570cc8Sopenharmony_ci
156869570cc8Sopenharmony_ci    return 0;
156969570cc8Sopenharmony_ci}
157069570cc8Sopenharmony_ci
157169570cc8Sopenharmony_ciAPPSPAWN_STATIC int AppspawnDevicedebugDeal(const char* op, int pid, cJSON *args)
157269570cc8Sopenharmony_ci{
157369570cc8Sopenharmony_ci    if (strcmp(op, "kill") == 0) {
157469570cc8Sopenharmony_ci        return AppspawpnDevicedebugKill(pid, args);
157569570cc8Sopenharmony_ci    }
157669570cc8Sopenharmony_ci
157769570cc8Sopenharmony_ci    APPSPAWN_LOGE("appspawn devicedebug op:%{public}s invaild", op);
157869570cc8Sopenharmony_ci
157969570cc8Sopenharmony_ci    return -1;
158069570cc8Sopenharmony_ci}
158169570cc8Sopenharmony_ci
158269570cc8Sopenharmony_ciAPPSPAWN_STATIC int ProcessAppSpawnDeviceDebugMsg(AppSpawnMsgNode *message)
158369570cc8Sopenharmony_ci{
158469570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(message != NULL, return -1);
158569570cc8Sopenharmony_ci    uint32_t len = 0;
158669570cc8Sopenharmony_ci
158769570cc8Sopenharmony_ci    const char* jsonString = (char *)GetAppSpawnMsgExtInfo(message, "devicedebug", &len);
158869570cc8Sopenharmony_ci    if (jsonString == NULL || len == 0) {
158969570cc8Sopenharmony_ci        APPSPAWN_LOGE("appspawn devicedebug get devicedebug fail");
159069570cc8Sopenharmony_ci        return -1;
159169570cc8Sopenharmony_ci    }
159269570cc8Sopenharmony_ci
159369570cc8Sopenharmony_ci    cJSON *json = cJSON_Parse(jsonString);
159469570cc8Sopenharmony_ci    if (json == NULL) {
159569570cc8Sopenharmony_ci        APPSPAWN_LOGE("appspawn devicedebug json parse fail");
159669570cc8Sopenharmony_ci        return -1;
159769570cc8Sopenharmony_ci    }
159869570cc8Sopenharmony_ci
159969570cc8Sopenharmony_ci    cJSON *app = cJSON_GetObjectItem(json, "app");
160069570cc8Sopenharmony_ci    if (!cJSON_IsNumber(app)) {
160169570cc8Sopenharmony_ci        APPSPAWN_LOGE("appspawn devicedebug json get app fail");
160269570cc8Sopenharmony_ci        return -1;
160369570cc8Sopenharmony_ci    }
160469570cc8Sopenharmony_ci
160569570cc8Sopenharmony_ci    cJSON *op = cJSON_GetObjectItem(json, "op");
160669570cc8Sopenharmony_ci    if (!cJSON_IsString(op) || op->valuestring == NULL) {
160769570cc8Sopenharmony_ci        APPSPAWN_LOGE("appspawn devicedebug json get op fail");
160869570cc8Sopenharmony_ci        return -1;
160969570cc8Sopenharmony_ci    }
161069570cc8Sopenharmony_ci
161169570cc8Sopenharmony_ci    cJSON *args = cJSON_GetObjectItem(json, "args");
161269570cc8Sopenharmony_ci    if (!cJSON_IsObject(args)) {
161369570cc8Sopenharmony_ci        APPSPAWN_LOGE("appspawn devicedebug json get args fail");
161469570cc8Sopenharmony_ci        return -1;
161569570cc8Sopenharmony_ci    }
161669570cc8Sopenharmony_ci
161769570cc8Sopenharmony_ci    return AppspawnDevicedebugDeal(op->valuestring, app->valueint, args);
161869570cc8Sopenharmony_ci}
161969570cc8Sopenharmony_ci
162069570cc8Sopenharmony_cistatic void ProcessRecvMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message)
162169570cc8Sopenharmony_ci{
162269570cc8Sopenharmony_ci    AppSpawnMsg *msg = &message->msgHeader;
162369570cc8Sopenharmony_ci    APPSPAWN_LOGI("Recv message header magic 0x%{public}x type %{public}u id %{public}u len %{public}u %{public}s",
162469570cc8Sopenharmony_ci        msg->magic, msg->msgType, msg->msgId, msg->msgLen, msg->processName);
162569570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_LOG(connection->receiverCtx.nextMsgId == msg->msgId,
162669570cc8Sopenharmony_ci        "Invalid msg id %{public}u %{public}u", connection->receiverCtx.nextMsgId, msg->msgId);
162769570cc8Sopenharmony_ci    connection->receiverCtx.nextMsgId++;
162869570cc8Sopenharmony_ci
162969570cc8Sopenharmony_ci    int ret;
163069570cc8Sopenharmony_ci    switch (msg->msgType) {
163169570cc8Sopenharmony_ci        case MSG_GET_RENDER_TERMINATION_STATUS: {  // get status
163269570cc8Sopenharmony_ci            AppSpawnResult result = {0};
163369570cc8Sopenharmony_ci            ret = ProcessTerminationStatusMsg(message, &result);
163469570cc8Sopenharmony_ci            SendResponse(connection, msg, ret == 0 ? result.result : ret, result.pid);
163569570cc8Sopenharmony_ci            DeleteAppSpawnMsg(message);
163669570cc8Sopenharmony_ci            break;
163769570cc8Sopenharmony_ci        }
163869570cc8Sopenharmony_ci        case MSG_SPAWN_NATIVE_PROCESS:  // spawn msg
163969570cc8Sopenharmony_ci        case MSG_APP_SPAWN: {
164069570cc8Sopenharmony_ci            ProcessSpawnReqMsg(connection, message);
164169570cc8Sopenharmony_ci            break;
164269570cc8Sopenharmony_ci        }
164369570cc8Sopenharmony_ci        case MSG_DUMP:
164469570cc8Sopenharmony_ci            ProcessAppSpawnDumpMsg(message);
164569570cc8Sopenharmony_ci            SendResponse(connection, msg, 0, 0);
164669570cc8Sopenharmony_ci            DeleteAppSpawnMsg(message);
164769570cc8Sopenharmony_ci            break;
164869570cc8Sopenharmony_ci        case MSG_BEGET_CMD: {
164969570cc8Sopenharmony_ci            ProcessBegetCmdMsg(connection, message);
165069570cc8Sopenharmony_ci            break;
165169570cc8Sopenharmony_ci        }
165269570cc8Sopenharmony_ci        case MSG_BEGET_SPAWNTIME:
165369570cc8Sopenharmony_ci            SendResponse(connection, msg, GetAppSpawnMgr()->spawnTime.minAppspawnTime,
165469570cc8Sopenharmony_ci                         GetAppSpawnMgr()->spawnTime.maxAppspawnTime);
165569570cc8Sopenharmony_ci            DeleteAppSpawnMsg(message);
165669570cc8Sopenharmony_ci            break;
165769570cc8Sopenharmony_ci        case MSG_UPDATE_MOUNT_POINTS:
165869570cc8Sopenharmony_ci            ret = ProcessSpawnRemountMsg(connection, message);
165969570cc8Sopenharmony_ci            SendResponse(connection, msg, ret, 0);
166069570cc8Sopenharmony_ci            break;
166169570cc8Sopenharmony_ci        case MSG_RESTART_SPAWNER:
166269570cc8Sopenharmony_ci            ProcessSpawnRestartMsg(connection, message);
166369570cc8Sopenharmony_ci            break;
166469570cc8Sopenharmony_ci        case MSG_DEVICE_DEBUG:
166569570cc8Sopenharmony_ci            ret = ProcessAppSpawnDeviceDebugMsg(message);
166669570cc8Sopenharmony_ci            SendResponse(connection, msg, ret, 0);
166769570cc8Sopenharmony_ci            DeleteAppSpawnMsg(message);
166869570cc8Sopenharmony_ci            break;
166969570cc8Sopenharmony_ci        default:
167069570cc8Sopenharmony_ci            SendResponse(connection, msg, APPSPAWN_MSG_INVALID, 0);
167169570cc8Sopenharmony_ci            DeleteAppSpawnMsg(message);
167269570cc8Sopenharmony_ci            break;
167369570cc8Sopenharmony_ci    }
167469570cc8Sopenharmony_ci}