14d6c458bSopenharmony_ci/*
24d6c458bSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
34d6c458bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44d6c458bSopenharmony_ci * you may not use this file except in compliance with the License.
54d6c458bSopenharmony_ci * You may obtain a copy of the License at
64d6c458bSopenharmony_ci *
74d6c458bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84d6c458bSopenharmony_ci *
94d6c458bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104d6c458bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114d6c458bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124d6c458bSopenharmony_ci * See the License for the specific language governing permissions and
134d6c458bSopenharmony_ci * limitations under the License.
144d6c458bSopenharmony_ci */
154d6c458bSopenharmony_ci
164d6c458bSopenharmony_ci#include "js_childprocess.h"
174d6c458bSopenharmony_ci
184d6c458bSopenharmony_ci#include <map>
194d6c458bSopenharmony_ci#include <vector>
204d6c458bSopenharmony_ci
214d6c458bSopenharmony_ci#include <csignal>
224d6c458bSopenharmony_ci#include <cstdlib>
234d6c458bSopenharmony_ci#include <sys/stat.h>
244d6c458bSopenharmony_ci#include <unistd.h>
254d6c458bSopenharmony_ci#include <sys/wait.h>
264d6c458bSopenharmony_ci
274d6c458bSopenharmony_ci#include "securec.h"
284d6c458bSopenharmony_ci#include "tools/log.h"
294d6c458bSopenharmony_ci
304d6c458bSopenharmony_cinamespace OHOS::JsSysModule::Process {
314d6c458bSopenharmony_ci    constexpr int MAXSIZE = 1024;
324d6c458bSopenharmony_ci    constexpr int TIME_EXCHANGE = 1000;
334d6c458bSopenharmony_ci    std::map<std::string, int> g_signalsMap = {
344d6c458bSopenharmony_ci        {"SIGHUP", 1},
354d6c458bSopenharmony_ci        {"SIGINT", 2},
364d6c458bSopenharmony_ci        {"SIGQUIT", 3},
374d6c458bSopenharmony_ci        {"SIGILL", 4},
384d6c458bSopenharmony_ci        {"SIGTRAP", 5},
394d6c458bSopenharmony_ci        {"SIGABRT", 6},
404d6c458bSopenharmony_ci        {"SIGBUS", 7},
414d6c458bSopenharmony_ci        {"SIGFPE", 8},
424d6c458bSopenharmony_ci        {"SIGKILL", 9},
434d6c458bSopenharmony_ci        {"SIGUSR1", 10},
444d6c458bSopenharmony_ci        {"SIGSEGV", 11},
454d6c458bSopenharmony_ci        {"SIGUSR2", 12},
464d6c458bSopenharmony_ci        {"SIGPIPE", 13},
474d6c458bSopenharmony_ci        {"SIGALRM", 14},
484d6c458bSopenharmony_ci        {"SIGTERM", 15},
494d6c458bSopenharmony_ci        {"SIGSTKFLT", 16},
504d6c458bSopenharmony_ci        {"SIGCHLD", 17},
514d6c458bSopenharmony_ci        {"SIGCONT", 18},
524d6c458bSopenharmony_ci        {"SIGSTOP", 19},
534d6c458bSopenharmony_ci        {"SIGTSTP", 20},
544d6c458bSopenharmony_ci        {"SIGTTIN", 21},
554d6c458bSopenharmony_ci        {"SIGTTOU", 22},
564d6c458bSopenharmony_ci        {"SIGURG", 23},
574d6c458bSopenharmony_ci        {"SIGXCPU", 24},
584d6c458bSopenharmony_ci        {"SIGXFSZ", 25},
594d6c458bSopenharmony_ci        {"SIGVTALRM", 26},
604d6c458bSopenharmony_ci        {"SIGPROF", 27},
614d6c458bSopenharmony_ci        {"SIGWINCH", 28},
624d6c458bSopenharmony_ci        {"SIGIO", 29},
634d6c458bSopenharmony_ci        {"SIGPWR", 30},
644d6c458bSopenharmony_ci        {"SIGSYS", 31}
654d6c458bSopenharmony_ci    };
664d6c458bSopenharmony_ci
674d6c458bSopenharmony_ci    void ChildProcess::Spawn(napi_env env, napi_value command)
684d6c458bSopenharmony_ci    {
694d6c458bSopenharmony_ci        int ret = pipe(stdOutFd_);
704d6c458bSopenharmony_ci        if (ret < 0) {
714d6c458bSopenharmony_ci            HILOG_ERROR("pipe1 failed %{public}d", errno);
724d6c458bSopenharmony_ci            return;
734d6c458bSopenharmony_ci        }
744d6c458bSopenharmony_ci        ret = pipe(stdErrFd_);
754d6c458bSopenharmony_ci        if (ret < 0) {
764d6c458bSopenharmony_ci            HILOG_ERROR("pipe2 failed %{public}d", errno);
774d6c458bSopenharmony_ci            return;
784d6c458bSopenharmony_ci        }
794d6c458bSopenharmony_ci        std::string strCommnd = RequireStrValue(env, command);
804d6c458bSopenharmony_ci        pid_t pid = fork();
814d6c458bSopenharmony_ci        if (!pid) {
824d6c458bSopenharmony_ci            close(stdErrFd_[0]);
834d6c458bSopenharmony_ci            close(stdOutFd_[0]);
844d6c458bSopenharmony_ci            dup2(stdOutFd_[1], 1);
854d6c458bSopenharmony_ci            dup2(stdErrFd_[1], 2); // 2:The value of parameter
864d6c458bSopenharmony_ci            if (execl("/bin/sh", "sh", "-c", strCommnd.c_str(), nullptr) == -1) {
874d6c458bSopenharmony_ci                HILOG_ERROR("execl command failed");
884d6c458bSopenharmony_ci                _exit(127); // 127:The parameter value
894d6c458bSopenharmony_ci            }
904d6c458bSopenharmony_ci        } else if (pid > 0) {
914d6c458bSopenharmony_ci            if (optionsInfo_ == nullptr) {
924d6c458bSopenharmony_ci                HILOG_ERROR("optionsInfo_ is nullptr");
934d6c458bSopenharmony_ci                return;
944d6c458bSopenharmony_ci            }
954d6c458bSopenharmony_ci            optionsInfo_->pid = pid;
964d6c458bSopenharmony_ci            ppid_ = getpid();
974d6c458bSopenharmony_ci            CreateWorker(env);
984d6c458bSopenharmony_ci            napi_value resourceName = nullptr;
994d6c458bSopenharmony_ci            napi_create_string_utf8(env, "TimeoutListener", strlen("TimeoutListener"), &resourceName);
1004d6c458bSopenharmony_ci            napi_create_async_work(
1014d6c458bSopenharmony_ci                env, nullptr, resourceName, TimeoutListener,
1024d6c458bSopenharmony_ci                [](napi_env env, napi_status status, void* data) {
1034d6c458bSopenharmony_ci                    OptionsInfo* optionsInfo = reinterpret_cast<OptionsInfo*>(data);
1044d6c458bSopenharmony_ci                    napi_delete_async_work(env, optionsInfo->worker);
1054d6c458bSopenharmony_ci                    delete optionsInfo;
1064d6c458bSopenharmony_ci                    optionsInfo = nullptr;
1074d6c458bSopenharmony_ci                },
1084d6c458bSopenharmony_ci                reinterpret_cast<void*>(optionsInfo_), &optionsInfo_->worker);
1094d6c458bSopenharmony_ci            napi_queue_async_work_with_qos(env, optionsInfo_->worker, napi_qos_user_initiated);
1104d6c458bSopenharmony_ci            close(stdErrFd_[1]);
1114d6c458bSopenharmony_ci            close(stdOutFd_[1]);
1124d6c458bSopenharmony_ci        } else {
1134d6c458bSopenharmony_ci            HILOG_ERROR("child process create failed");
1144d6c458bSopenharmony_ci        }
1154d6c458bSopenharmony_ci    }
1164d6c458bSopenharmony_ci
1174d6c458bSopenharmony_ci    napi_value ChildProcess::Wait(napi_env env)
1184d6c458bSopenharmony_ci    {
1194d6c458bSopenharmony_ci        napi_value promise = nullptr;
1204d6c458bSopenharmony_ci        auto waitInfo = new WaitInfo;
1214d6c458bSopenharmony_ci        napi_create_promise(env, &(waitInfo->deferred), &promise);
1224d6c458bSopenharmony_ci
1234d6c458bSopenharmony_ci        if (isWait_) {
1244d6c458bSopenharmony_ci            int32_t status;
1254d6c458bSopenharmony_ci            isWait_ = false;
1264d6c458bSopenharmony_ci            if (optionsInfo_ == nullptr) {
1274d6c458bSopenharmony_ci                napi_value res = nullptr;
1284d6c458bSopenharmony_ci                napi_get_undefined(env, &res);
1294d6c458bSopenharmony_ci                delete waitInfo;
1304d6c458bSopenharmony_ci                waitInfo = nullptr;
1314d6c458bSopenharmony_ci                HILOG_ERROR("optionsInfo_ is nullptr");
1324d6c458bSopenharmony_ci                return res;
1334d6c458bSopenharmony_ci            }
1344d6c458bSopenharmony_ci            waitpid(optionsInfo_->pid, &status, 0);
1354d6c458bSopenharmony_ci            exitCode_ = status;
1364d6c458bSopenharmony_ci        }
1374d6c458bSopenharmony_ci        isNeedRun_ = false;
1384d6c458bSopenharmony_ci        napi_value result = nullptr;
1394d6c458bSopenharmony_ci        napi_create_int32(env, static_cast<int8_t>(exitCode_), &result);
1404d6c458bSopenharmony_ci        napi_resolve_deferred(env, waitInfo->deferred, result);
1414d6c458bSopenharmony_ci        delete waitInfo;
1424d6c458bSopenharmony_ci        waitInfo = nullptr;
1434d6c458bSopenharmony_ci
1444d6c458bSopenharmony_ci        return promise;
1454d6c458bSopenharmony_ci    }
1464d6c458bSopenharmony_ci
1474d6c458bSopenharmony_ci    napi_value ChildProcess::GetOutput(napi_env env) const
1484d6c458bSopenharmony_ci    {
1494d6c458bSopenharmony_ci        if (stdOutInfo_ == nullptr) {
1504d6c458bSopenharmony_ci            napi_value res = nullptr;
1514d6c458bSopenharmony_ci            NAPI_CALL(env, napi_get_undefined(env, &res));
1524d6c458bSopenharmony_ci            HILOG_ERROR("stdOutInfo_ is nullptr");
1534d6c458bSopenharmony_ci            return res;
1544d6c458bSopenharmony_ci        }
1554d6c458bSopenharmony_ci        NAPI_CALL(env, napi_create_promise(env, &stdOutInfo_->deferred, &stdOutInfo_->promise));
1564d6c458bSopenharmony_ci        void* data = nullptr;
1574d6c458bSopenharmony_ci        napi_value arrayBuffer = nullptr;
1584d6c458bSopenharmony_ci        size_t bufferSize = stdOutInfo_->stdData.size() + 1;
1594d6c458bSopenharmony_ci        NAPI_CALL(env, napi_create_arraybuffer(env, bufferSize, &data, &arrayBuffer));
1604d6c458bSopenharmony_ci        if (memcpy_s(data, bufferSize, reinterpret_cast<const void*>(stdOutInfo_->stdData.c_str()),
1614d6c458bSopenharmony_ci            stdOutInfo_->stdData.size()) != EOK) {
1624d6c458bSopenharmony_ci            HILOG_ERROR("getOutput memcpy_s failed");
1634d6c458bSopenharmony_ci            NAPI_CALL(env, napi_delete_async_work(env, stdOutInfo_->worker));
1644d6c458bSopenharmony_ci            napi_value res = nullptr;
1654d6c458bSopenharmony_ci            NAPI_CALL(env, napi_get_undefined(env, &res));
1664d6c458bSopenharmony_ci            return res;
1674d6c458bSopenharmony_ci        }
1684d6c458bSopenharmony_ci
1694d6c458bSopenharmony_ci        napi_value result = nullptr;
1704d6c458bSopenharmony_ci        NAPI_CALL(env, napi_create_typedarray(env, napi_uint8_array, bufferSize, arrayBuffer, 0, &result));
1714d6c458bSopenharmony_ci        NAPI_CALL(env, napi_resolve_deferred(env, stdOutInfo_->deferred, result));
1724d6c458bSopenharmony_ci        return stdOutInfo_->promise;
1734d6c458bSopenharmony_ci    }
1744d6c458bSopenharmony_ci
1754d6c458bSopenharmony_ci    napi_value ChildProcess::GetErrorOutput(napi_env env) const
1764d6c458bSopenharmony_ci    {
1774d6c458bSopenharmony_ci        if (stdErrInfo_ == nullptr) {
1784d6c458bSopenharmony_ci            napi_value res = nullptr;
1794d6c458bSopenharmony_ci            NAPI_CALL(env, napi_get_undefined(env, &res));
1804d6c458bSopenharmony_ci            HILOG_ERROR("stdErrInfo_ is nullptr");
1814d6c458bSopenharmony_ci            return res;
1824d6c458bSopenharmony_ci        }
1834d6c458bSopenharmony_ci        NAPI_CALL(env, napi_create_promise(env, &stdErrInfo_->deferred, &stdErrInfo_->promise));
1844d6c458bSopenharmony_ci        void* data = nullptr;
1854d6c458bSopenharmony_ci        napi_value arrayBuffer = nullptr;
1864d6c458bSopenharmony_ci        size_t bufferSize = stdErrInfo_->stdData.size() + 1;
1874d6c458bSopenharmony_ci        NAPI_CALL(env, napi_create_arraybuffer(env, bufferSize, &data, &arrayBuffer));
1884d6c458bSopenharmony_ci        if (memcpy_s(data, bufferSize, reinterpret_cast<const void*>(stdErrInfo_->stdData.c_str()),
1894d6c458bSopenharmony_ci            stdErrInfo_->stdData.size()) != EOK) {
1904d6c458bSopenharmony_ci            HILOG_ERROR("getErrOutput memcpy_s failed");
1914d6c458bSopenharmony_ci            NAPI_CALL(env, napi_delete_async_work(env, stdErrInfo_->worker));
1924d6c458bSopenharmony_ci            napi_value res = nullptr;
1934d6c458bSopenharmony_ci            NAPI_CALL(env, napi_get_undefined(env, &res));
1944d6c458bSopenharmony_ci            return res;
1954d6c458bSopenharmony_ci        }
1964d6c458bSopenharmony_ci
1974d6c458bSopenharmony_ci        napi_value result = nullptr;
1984d6c458bSopenharmony_ci        NAPI_CALL(env, napi_create_typedarray(env, napi_uint8_array, bufferSize, arrayBuffer, 0, &result));
1994d6c458bSopenharmony_ci        NAPI_CALL(env, napi_resolve_deferred(env, stdErrInfo_->deferred, result));
2004d6c458bSopenharmony_ci        return stdErrInfo_->promise;
2014d6c458bSopenharmony_ci    }
2024d6c458bSopenharmony_ci
2034d6c458bSopenharmony_ci    napi_value ChildProcess::GetKilled(napi_env env) const
2044d6c458bSopenharmony_ci    {
2054d6c458bSopenharmony_ci        napi_value result = nullptr;
2064d6c458bSopenharmony_ci        NAPI_CALL(env, napi_get_boolean(env, killed_, &result));
2074d6c458bSopenharmony_ci
2084d6c458bSopenharmony_ci        return result;
2094d6c458bSopenharmony_ci    }
2104d6c458bSopenharmony_ci
2114d6c458bSopenharmony_ci    napi_value ChildProcess::Getpid(napi_env env) const
2124d6c458bSopenharmony_ci    {
2134d6c458bSopenharmony_ci        napi_value result = nullptr;
2144d6c458bSopenharmony_ci        if (optionsInfo_ == nullptr) {
2154d6c458bSopenharmony_ci            napi_value res = nullptr;
2164d6c458bSopenharmony_ci            NAPI_CALL(env, napi_get_undefined(env, &res));
2174d6c458bSopenharmony_ci            HILOG_ERROR("optionsInfo_ is nullptr");
2184d6c458bSopenharmony_ci            return res;
2194d6c458bSopenharmony_ci        }
2204d6c458bSopenharmony_ci        NAPI_CALL(env, napi_create_int32(env, optionsInfo_->pid, &result));
2214d6c458bSopenharmony_ci
2224d6c458bSopenharmony_ci        return result;
2234d6c458bSopenharmony_ci    }
2244d6c458bSopenharmony_ci
2254d6c458bSopenharmony_ci    napi_value ChildProcess::Getppid(napi_env env) const
2264d6c458bSopenharmony_ci    {
2274d6c458bSopenharmony_ci        napi_value result = nullptr;
2284d6c458bSopenharmony_ci        NAPI_CALL(env, napi_create_int32(env, ppid_, &result));
2294d6c458bSopenharmony_ci
2304d6c458bSopenharmony_ci        return result;
2314d6c458bSopenharmony_ci    }
2324d6c458bSopenharmony_ci
2334d6c458bSopenharmony_ci    napi_value ChildProcess::GetExitCode(napi_env env) const
2344d6c458bSopenharmony_ci    {
2354d6c458bSopenharmony_ci        napi_value result = nullptr;
2364d6c458bSopenharmony_ci        NAPI_CALL(env, napi_create_int32(env, static_cast<int8_t>(exitCode_), &result));
2374d6c458bSopenharmony_ci
2384d6c458bSopenharmony_ci        return result;
2394d6c458bSopenharmony_ci    }
2404d6c458bSopenharmony_ci
2414d6c458bSopenharmony_ci    void ChildProcess::CreateWorker(napi_env env)
2424d6c458bSopenharmony_ci    {
2434d6c458bSopenharmony_ci        // getstdout
2444d6c458bSopenharmony_ci        napi_value resourceName = nullptr;
2454d6c458bSopenharmony_ci        stdOutInfo_ = new StdInfo();
2464d6c458bSopenharmony_ci        if (stdOutInfo_ == nullptr) {
2474d6c458bSopenharmony_ci            HILOG_ERROR("stdOutInfo_ is nullptr");
2484d6c458bSopenharmony_ci            return;
2494d6c458bSopenharmony_ci        }
2504d6c458bSopenharmony_ci        stdOutInfo_->isNeedRun = &isNeedRun_;
2514d6c458bSopenharmony_ci        stdOutInfo_->fd = stdOutFd_[0];
2524d6c458bSopenharmony_ci        if (optionsInfo_ == nullptr) {
2534d6c458bSopenharmony_ci            HILOG_ERROR("optionsInfo_ is nullptr");
2544d6c458bSopenharmony_ci            return;
2554d6c458bSopenharmony_ci        }
2564d6c458bSopenharmony_ci        stdOutInfo_->pid = optionsInfo_->pid;
2574d6c458bSopenharmony_ci        stdOutInfo_->maxBuffSize = optionsInfo_->maxBuffer;
2584d6c458bSopenharmony_ci        napi_create_string_utf8(env, "ReadStdOut", NAPI_AUTO_LENGTH, &resourceName);
2594d6c458bSopenharmony_ci        napi_create_async_work(env, nullptr, resourceName, ReadStdOut, EndStdOut,
2604d6c458bSopenharmony_ci                               reinterpret_cast<void*>(stdOutInfo_), &stdOutInfo_->worker);
2614d6c458bSopenharmony_ci        napi_queue_async_work_with_qos(env, stdOutInfo_->worker, napi_qos_user_initiated);
2624d6c458bSopenharmony_ci
2634d6c458bSopenharmony_ci        // getstderr
2644d6c458bSopenharmony_ci        stdErrInfo_ = new StdInfo();
2654d6c458bSopenharmony_ci        if (stdErrInfo_ == nullptr) {
2664d6c458bSopenharmony_ci            HILOG_ERROR("stdErrInfo_ is nullptr");
2674d6c458bSopenharmony_ci            return;
2684d6c458bSopenharmony_ci        }
2694d6c458bSopenharmony_ci        stdErrInfo_->isNeedRun = &isNeedRun_;
2704d6c458bSopenharmony_ci        stdErrInfo_->fd = stdErrFd_[0];
2714d6c458bSopenharmony_ci        stdErrInfo_->pid = optionsInfo_->pid;
2724d6c458bSopenharmony_ci        stdErrInfo_->maxBuffSize = optionsInfo_->maxBuffer;
2734d6c458bSopenharmony_ci        napi_create_string_utf8(env, "ReadStdErr", NAPI_AUTO_LENGTH, &resourceName);
2744d6c458bSopenharmony_ci        napi_create_async_work(env, nullptr, resourceName, ReadStdErr, EndStdErr,
2754d6c458bSopenharmony_ci                               reinterpret_cast<void*>(stdErrInfo_), &stdErrInfo_->worker);
2764d6c458bSopenharmony_ci        napi_queue_async_work_with_qos(env, stdErrInfo_->worker, napi_qos_user_initiated);
2774d6c458bSopenharmony_ci    }
2784d6c458bSopenharmony_ci
2794d6c458bSopenharmony_ci    void ChildProcess::ReadStdOut(napi_env env, void* data)
2804d6c458bSopenharmony_ci    {
2814d6c458bSopenharmony_ci        auto stdOutInfo = reinterpret_cast<StdInfo*>(data);
2824d6c458bSopenharmony_ci        char childStdout[MAXSIZE] = {0};
2834d6c458bSopenharmony_ci        if (stdOutInfo->isNeedRun == nullptr) {
2844d6c458bSopenharmony_ci            return;
2854d6c458bSopenharmony_ci        }
2864d6c458bSopenharmony_ci        while (*(stdOutInfo->isNeedRun)) {
2874d6c458bSopenharmony_ci            auto readSize = read(stdOutInfo->fd, childStdout, sizeof(childStdout) - 1);
2884d6c458bSopenharmony_ci            if (readSize >= 0) {
2894d6c458bSopenharmony_ci                stdOutInfo->stdData += childStdout;
2904d6c458bSopenharmony_ci            }
2914d6c458bSopenharmony_ci            if (stdOutInfo->stdData.size() > static_cast<size_t>(stdOutInfo->maxBuffSize) && *(stdOutInfo->isNeedRun)) {
2924d6c458bSopenharmony_ci                if (!kill(stdOutInfo->pid, SIGKILL)) {
2934d6c458bSopenharmony_ci                    *(stdOutInfo->isNeedRun) = false;
2944d6c458bSopenharmony_ci                    stdOutInfo->stdData = stdOutInfo->stdData.substr(0, stdOutInfo->maxBuffSize);
2954d6c458bSopenharmony_ci                } else {
2964d6c458bSopenharmony_ci                    HILOG_ERROR("stdOut maxBuff kill signal failed");
2974d6c458bSopenharmony_ci                }
2984d6c458bSopenharmony_ci            }
2994d6c458bSopenharmony_ci            if (memset_s(childStdout, sizeof(childStdout), '\0', MAXSIZE) != EOK) {
3004d6c458bSopenharmony_ci                HILOG_ERROR("getOutput memset_s failed");
3014d6c458bSopenharmony_ci                return;
3024d6c458bSopenharmony_ci            }
3034d6c458bSopenharmony_ci        }
3044d6c458bSopenharmony_ci    }
3054d6c458bSopenharmony_ci
3064d6c458bSopenharmony_ci    void ChildProcess::EndStdOut(napi_env env, napi_status status, void* buffer)
3074d6c458bSopenharmony_ci    {
3084d6c458bSopenharmony_ci        auto stdOutInfo = reinterpret_cast<StdInfo*>(buffer);
3094d6c458bSopenharmony_ci        napi_delete_async_work(env, stdOutInfo->worker);
3104d6c458bSopenharmony_ci        delete stdOutInfo;
3114d6c458bSopenharmony_ci        stdOutInfo = nullptr;
3124d6c458bSopenharmony_ci    }
3134d6c458bSopenharmony_ci
3144d6c458bSopenharmony_ci    void ChildProcess::ReadStdErr(napi_env env, void* data)
3154d6c458bSopenharmony_ci    {
3164d6c458bSopenharmony_ci        auto stdErrInfo = reinterpret_cast<StdInfo*>(data);
3174d6c458bSopenharmony_ci        char childStderr[MAXSIZE] = {0};
3184d6c458bSopenharmony_ci        if (stdErrInfo->isNeedRun == nullptr) {
3194d6c458bSopenharmony_ci            return;
3204d6c458bSopenharmony_ci        }
3214d6c458bSopenharmony_ci        while (*(stdErrInfo->isNeedRun)) {
3224d6c458bSopenharmony_ci            auto readSize = read(stdErrInfo->fd, childStderr, sizeof(childStderr) - 1);
3234d6c458bSopenharmony_ci            if (readSize >= 0) {
3244d6c458bSopenharmony_ci                stdErrInfo->stdData += childStderr;
3254d6c458bSopenharmony_ci            }
3264d6c458bSopenharmony_ci            if (stdErrInfo->stdData.size() > static_cast<size_t>(stdErrInfo->maxBuffSize) && *(stdErrInfo->isNeedRun)) {
3274d6c458bSopenharmony_ci                if (!kill(stdErrInfo->pid, SIGKILL)) {
3284d6c458bSopenharmony_ci                    *(stdErrInfo->isNeedRun) = false;
3294d6c458bSopenharmony_ci                    stdErrInfo->stdData = stdErrInfo->stdData.substr(0, stdErrInfo->maxBuffSize);
3304d6c458bSopenharmony_ci                } else {
3314d6c458bSopenharmony_ci                    HILOG_ERROR("stdErr maxBuff kill signal failed");
3324d6c458bSopenharmony_ci                }
3334d6c458bSopenharmony_ci            }
3344d6c458bSopenharmony_ci            if (memset_s(childStderr, sizeof(childStderr), '\0', MAXSIZE) != EOK) {
3354d6c458bSopenharmony_ci                HILOG_ERROR("getOutput memset_s failed");
3364d6c458bSopenharmony_ci                return;
3374d6c458bSopenharmony_ci            }
3384d6c458bSopenharmony_ci        }
3394d6c458bSopenharmony_ci    }
3404d6c458bSopenharmony_ci
3414d6c458bSopenharmony_ci    void ChildProcess::EndStdErr(napi_env env, napi_status status, void* buffer)
3424d6c458bSopenharmony_ci    {
3434d6c458bSopenharmony_ci        auto stdErrInfo = reinterpret_cast<StdInfo*>(buffer);
3444d6c458bSopenharmony_ci        napi_delete_async_work(env, stdErrInfo->worker);
3454d6c458bSopenharmony_ci        delete stdErrInfo;
3464d6c458bSopenharmony_ci        stdErrInfo = nullptr;
3474d6c458bSopenharmony_ci    }
3484d6c458bSopenharmony_ci
3494d6c458bSopenharmony_ci    int ChildProcess::GetValidSignal(napi_env env, const napi_value signo)
3504d6c458bSopenharmony_ci    {
3514d6c458bSopenharmony_ci        int32_t sig = 0;
3524d6c458bSopenharmony_ci        napi_valuetype valuetype = napi_undefined;
3534d6c458bSopenharmony_ci        napi_typeof(env, signo, &valuetype);
3544d6c458bSopenharmony_ci        if (valuetype == napi_valuetype::napi_number) {
3554d6c458bSopenharmony_ci            napi_get_value_int32(env, signo, &sig);
3564d6c458bSopenharmony_ci            return sig;
3574d6c458bSopenharmony_ci        } else if (valuetype == napi_valuetype::napi_string) {
3584d6c458bSopenharmony_ci            std::string buffer = RequireStrValue(env, signo);
3594d6c458bSopenharmony_ci            auto iter = g_signalsMap.find(buffer);
3604d6c458bSopenharmony_ci            if (iter != g_signalsMap.end()) {
3614d6c458bSopenharmony_ci                sig = iter->second;
3624d6c458bSopenharmony_ci                return sig;
3634d6c458bSopenharmony_ci            } else {
3644d6c458bSopenharmony_ci                return g_signalsMap["SIGTERM"];
3654d6c458bSopenharmony_ci            }
3664d6c458bSopenharmony_ci        } else {
3674d6c458bSopenharmony_ci            return g_signalsMap["SIGTERM"];
3684d6c458bSopenharmony_ci        }
3694d6c458bSopenharmony_ci    }
3704d6c458bSopenharmony_ci
3714d6c458bSopenharmony_ci    void ChildProcess::Kill(napi_env env, const napi_value signo)
3724d6c458bSopenharmony_ci    {
3734d6c458bSopenharmony_ci        int signal = GetValidSignal(env, signo);
3744d6c458bSopenharmony_ci        std::vector<int32_t> signalType = {SIGINT, SIGQUIT, SIGKILL, SIGTERM};
3754d6c458bSopenharmony_ci        if (optionsInfo_ == nullptr) {
3764d6c458bSopenharmony_ci            HILOG_ERROR("optionsInfo_ is nullptr");
3774d6c458bSopenharmony_ci            return;
3784d6c458bSopenharmony_ci        }
3794d6c458bSopenharmony_ci        if (!kill(optionsInfo_->pid, signal)) {
3804d6c458bSopenharmony_ci            auto res = std::find(signalType.begin(), signalType.end(), static_cast<int32_t>(signal));
3814d6c458bSopenharmony_ci            (res != signalType.end()) ? isNeedRun_ = false : 0;
3824d6c458bSopenharmony_ci            killed_ = true;
3834d6c458bSopenharmony_ci        } else {
3844d6c458bSopenharmony_ci            HILOG_ERROR("kill signal failed");
3854d6c458bSopenharmony_ci        }
3864d6c458bSopenharmony_ci    }
3874d6c458bSopenharmony_ci
3884d6c458bSopenharmony_ci    void ChildProcess::Close()
3894d6c458bSopenharmony_ci    {
3904d6c458bSopenharmony_ci        int32_t status = 0;
3914d6c458bSopenharmony_ci        if (optionsInfo_ == nullptr) {
3924d6c458bSopenharmony_ci            HILOG_ERROR("optionsInfo_ is nullptr");
3934d6c458bSopenharmony_ci            return;
3944d6c458bSopenharmony_ci        }
3954d6c458bSopenharmony_ci        if (isWait_ && !(waitpid(optionsInfo_->pid, &status, WNOHANG)) && isNeedRun_) {
3964d6c458bSopenharmony_ci            if (!kill(optionsInfo_->pid, SIGKILL)) {
3974d6c458bSopenharmony_ci                waitpid(optionsInfo_->pid, &status, 0);
3984d6c458bSopenharmony_ci                isWait_ = false;
3994d6c458bSopenharmony_ci                exitCode_ = status;
4004d6c458bSopenharmony_ci                isNeedRun_ = false;
4014d6c458bSopenharmony_ci            } else {
4024d6c458bSopenharmony_ci                HILOG_ERROR("close kill SIGKILL signal failed");
4034d6c458bSopenharmony_ci            }
4044d6c458bSopenharmony_ci        }
4054d6c458bSopenharmony_ci    }
4064d6c458bSopenharmony_ci
4074d6c458bSopenharmony_ci    void ChildProcess::TimeoutListener(napi_env env, void* data)
4084d6c458bSopenharmony_ci    {
4094d6c458bSopenharmony_ci        std::vector<int32_t> signalType = {SIGINT, SIGQUIT, SIGKILL, SIGTERM};
4104d6c458bSopenharmony_ci        auto temp = reinterpret_cast<OptionsInfo*>(data);
4114d6c458bSopenharmony_ci        int32_t timeout = temp->timeout * TIME_EXCHANGE;
4124d6c458bSopenharmony_ci        if (timeout > 0) {
4134d6c458bSopenharmony_ci            usleep(static_cast<size_t>(timeout));
4144d6c458bSopenharmony_ci            if (*(temp->isNeedRun)) {
4154d6c458bSopenharmony_ci                if (!kill(temp->pid, temp->killSignal)) {
4164d6c458bSopenharmony_ci                    auto res = std::find(signalType.begin(), signalType.end(), temp->killSignal);
4174d6c458bSopenharmony_ci                    (res != signalType.end()) ? *(temp->isNeedRun) = false : 0;
4184d6c458bSopenharmony_ci                } else {
4194d6c458bSopenharmony_ci                    HILOG_ERROR("timeout kill signal failed");
4204d6c458bSopenharmony_ci                }
4214d6c458bSopenharmony_ci            }
4224d6c458bSopenharmony_ci        }
4234d6c458bSopenharmony_ci    }
4244d6c458bSopenharmony_ci
4254d6c458bSopenharmony_ci    void ChildProcess::InitOptionsInfo(napi_env env, napi_value options)
4264d6c458bSopenharmony_ci    {
4274d6c458bSopenharmony_ci        std::vector<std::string> keyStr = {"timeout", "killSignal", "maxBuffer"};
4284d6c458bSopenharmony_ci        optionsInfo_ = new OptionsInfo();
4294d6c458bSopenharmony_ci        if (optionsInfo_ == nullptr) {
4304d6c458bSopenharmony_ci            HILOG_ERROR("optionsInfo_ is nullptr");
4314d6c458bSopenharmony_ci            return;
4324d6c458bSopenharmony_ci        }
4334d6c458bSopenharmony_ci        size_t size = keyStr.size();
4344d6c458bSopenharmony_ci        for (size_t i = 0; i < size; i++) {
4354d6c458bSopenharmony_ci            napi_status status = napi_ok;
4364d6c458bSopenharmony_ci            napi_value property = nullptr;
4374d6c458bSopenharmony_ci            napi_get_named_property(env, options, keyStr[i].c_str(), &property);
4384d6c458bSopenharmony_ci            switch (i) {
4394d6c458bSopenharmony_ci                case 0:
4404d6c458bSopenharmony_ci                    status = napi_get_value_int32(env, property, &optionsInfo_->timeout);
4414d6c458bSopenharmony_ci                    if (status != napi_ok) {
4424d6c458bSopenharmony_ci                        optionsInfo_->timeout = 0;
4434d6c458bSopenharmony_ci                    }
4444d6c458bSopenharmony_ci                    break;
4454d6c458bSopenharmony_ci                case 1:
4464d6c458bSopenharmony_ci                    optionsInfo_->killSignal = GetValidSignal(env, property);
4474d6c458bSopenharmony_ci                    break;
4484d6c458bSopenharmony_ci                case 2: // 2:The parameter value
4494d6c458bSopenharmony_ci                    status = napi_get_value_int64(env, property, &optionsInfo_->maxBuffer);
4504d6c458bSopenharmony_ci                    if (status != napi_ok) {
4514d6c458bSopenharmony_ci                        optionsInfo_->maxBuffer = static_cast<int64_t>(MAXSIZE) * static_cast<int64_t>(MAXSIZE);
4524d6c458bSopenharmony_ci                    }
4534d6c458bSopenharmony_ci                    break;
4544d6c458bSopenharmony_ci                default:
4554d6c458bSopenharmony_ci                    break;
4564d6c458bSopenharmony_ci            }
4574d6c458bSopenharmony_ci        }
4584d6c458bSopenharmony_ci        optionsInfo_->isNeedRun = &isNeedRun_;
4594d6c458bSopenharmony_ci    }
4604d6c458bSopenharmony_ci
4614d6c458bSopenharmony_ci    std::string ChildProcess::RequireStrValue(napi_env env, const napi_value strValue)
4624d6c458bSopenharmony_ci    {
4634d6c458bSopenharmony_ci        size_t bufferSize = 0;
4644d6c458bSopenharmony_ci        if (napi_get_value_string_utf8(env, strValue, nullptr, 0, &bufferSize) != napi_ok) {
4654d6c458bSopenharmony_ci            HILOG_ERROR("can not get strValue size");
4664d6c458bSopenharmony_ci            return nullptr;
4674d6c458bSopenharmony_ci        }
4684d6c458bSopenharmony_ci        std::string result = "";
4694d6c458bSopenharmony_ci        result.reserve(bufferSize + 1);
4704d6c458bSopenharmony_ci        result.resize(bufferSize);
4714d6c458bSopenharmony_ci        if (napi_get_value_string_utf8(env, strValue, result.data(), bufferSize + 1, &bufferSize) != napi_ok) {
4724d6c458bSopenharmony_ci            HILOG_ERROR("can not get strValue value");
4734d6c458bSopenharmony_ci            return nullptr;
4744d6c458bSopenharmony_ci        }
4754d6c458bSopenharmony_ci        return result;
4764d6c458bSopenharmony_ci    }
4774d6c458bSopenharmony_ci
4784d6c458bSopenharmony_ci    ChildProcess::~ChildProcess()
4794d6c458bSopenharmony_ci    {
4804d6c458bSopenharmony_ci        close(stdOutFd_[0]);
4814d6c458bSopenharmony_ci        close(stdErrFd_[0]);
4824d6c458bSopenharmony_ci        if (isWait_) {
4834d6c458bSopenharmony_ci            int32_t status = 0;
4844d6c458bSopenharmony_ci            waitpid(optionsInfo_->pid, &status, 0);
4854d6c458bSopenharmony_ci        }
4864d6c458bSopenharmony_ci        isNeedRun_ = false;
4874d6c458bSopenharmony_ci    }
4884d6c458bSopenharmony_ci} // namespace OHOS::JsSysModule::Process
489