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