1cc290419Sopenharmony_ci/*
2cc290419Sopenharmony_ci * Copyright (C) 2021 Huawei Device Co., Ltd.
3cc290419Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4cc290419Sopenharmony_ci * you may not use this file except in compliance with the License.
5cc290419Sopenharmony_ci * You may obtain a copy of the License at
6cc290419Sopenharmony_ci *
7cc290419Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8cc290419Sopenharmony_ci *
9cc290419Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10cc290419Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11cc290419Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12cc290419Sopenharmony_ci * See the License for the specific language governing permissions and
13cc290419Sopenharmony_ci * limitations under the License.
14cc290419Sopenharmony_ci *
15cc290419Sopenharmony_ci */
16cc290419Sopenharmony_ci// The process is used to test jdwp.
17cc290419Sopenharmony_ci// jpid List pids of processes hosting a JDWP transport
18cc290419Sopenharmony_ci#include "define.h"
19cc290419Sopenharmony_ci#include "HdcJdwpSimulator.h"
20cc290419Sopenharmony_ciusing namespace OHOS::HiviewDFX;
21cc290419Sopenharmony_cistatic constexpr HiLogLabel LABEL = {LOG_CORE, 0, "JDWP_TEST"};
22cc290419Sopenharmony_cistatic uv_loop_t loopMain;
23cc290419Sopenharmony_cistatic HdcJdwpSimulator *clsHdcJdwpSimulator = nullptr;
24cc290419Sopenharmony_ci
25cc290419Sopenharmony_cistatic void PrintMessage(const char *fmt, ...)
26cc290419Sopenharmony_ci{
27cc290419Sopenharmony_ci    int ret = 0;
28cc290419Sopenharmony_ci    va_list ap;
29cc290419Sopenharmony_ci    va_start(ap, fmt);
30cc290419Sopenharmony_ci    vfprintf(stdout, fmt, ap);
31cc290419Sopenharmony_ci    ret = fprintf(stdout, "\n");
32cc290419Sopenharmony_ci    va_end(ap);
33cc290419Sopenharmony_ci}
34cc290419Sopenharmony_ci
35cc290419Sopenharmony_cistatic void TryCloseHandle(const uv_handle_t *handle, bool alwaysCallback,
36cc290419Sopenharmony_ci                           uv_close_cb closeCallBack)
37cc290419Sopenharmony_ci{
38cc290419Sopenharmony_ci    bool hasCallClose = false;
39cc290419Sopenharmony_ci    if (handle->loop && !uv_is_closing(handle)) {
40cc290419Sopenharmony_ci        uv_close((uv_handle_t *)handle, closeCallBack);
41cc290419Sopenharmony_ci        hasCallClose = true;
42cc290419Sopenharmony_ci    }
43cc290419Sopenharmony_ci    if (!hasCallClose && alwaysCallback) {
44cc290419Sopenharmony_ci        closeCallBack((uv_handle_t *)handle);
45cc290419Sopenharmony_ci    }
46cc290419Sopenharmony_ci}
47cc290419Sopenharmony_ci
48cc290419Sopenharmony_cistatic void TryCloseHandle(const uv_handle_t *handle, uv_close_cb closeCallBack)
49cc290419Sopenharmony_ci{
50cc290419Sopenharmony_ci    TryCloseHandle(handle, false, closeCallBack);
51cc290419Sopenharmony_ci}
52cc290419Sopenharmony_ci
53cc290419Sopenharmony_cistatic void TryCloseHandle(const uv_handle_t *handle)
54cc290419Sopenharmony_ci{
55cc290419Sopenharmony_ci    TryCloseHandle(handle, nullptr);
56cc290419Sopenharmony_ci}
57cc290419Sopenharmony_ci
58cc290419Sopenharmony_cistatic bool TryCloseLoop(uv_loop_t *ptrLoop, const char *callerName)
59cc290419Sopenharmony_ci{
60cc290419Sopenharmony_ci    uint8_t closeRetry = 0;
61cc290419Sopenharmony_ci    bool ret = false;
62cc290419Sopenharmony_ci    constexpr int maxRetry = 3;
63cc290419Sopenharmony_ci    constexpr int maxHandle = 2;
64cc290419Sopenharmony_ci    for (closeRetry = 0; closeRetry < maxRetry; ++closeRetry) {
65cc290419Sopenharmony_ci        if (uv_loop_close(ptrLoop) == UV_EBUSY) {
66cc290419Sopenharmony_ci            if (closeRetry > maxRetry) {
67cc290419Sopenharmony_ci                PrintMessage("%s close busy,try:%d", callerName, closeRetry);
68cc290419Sopenharmony_ci            }
69cc290419Sopenharmony_ci
70cc290419Sopenharmony_ci            if (ptrLoop->active_handles >= maxHandle) {
71cc290419Sopenharmony_ci                PrintMessage("TryCloseLoop issue");
72cc290419Sopenharmony_ci            }
73cc290419Sopenharmony_ci            auto clearLoopTask = [](uv_handle_t *handle, void *arg) -> void {
74cc290419Sopenharmony_ci                TryCloseHandle(handle);
75cc290419Sopenharmony_ci            };
76cc290419Sopenharmony_ci            uv_walk(ptrLoop, clearLoopTask, nullptr);
77cc290419Sopenharmony_ci            // If all processing ends, Then return0,this call will block
78cc290419Sopenharmony_ci            if (!ptrLoop->active_handles) {
79cc290419Sopenharmony_ci                ret = true;
80cc290419Sopenharmony_ci                break;
81cc290419Sopenharmony_ci            }
82cc290419Sopenharmony_ci            if (!uv_run(ptrLoop, UV_RUN_ONCE)) {
83cc290419Sopenharmony_ci                ret = true;
84cc290419Sopenharmony_ci                break;
85cc290419Sopenharmony_ci            }
86cc290419Sopenharmony_ci        } else {
87cc290419Sopenharmony_ci            ret = true;
88cc290419Sopenharmony_ci            break;
89cc290419Sopenharmony_ci        }
90cc290419Sopenharmony_ci    }
91cc290419Sopenharmony_ci    return ret;
92cc290419Sopenharmony_ci}
93cc290419Sopenharmony_ci
94cc290419Sopenharmony_cistatic void FreeInstance()
95cc290419Sopenharmony_ci{
96cc290419Sopenharmony_ci    if (clsHdcJdwpSimulator) {
97cc290419Sopenharmony_ci        clsHdcJdwpSimulator->stop();
98cc290419Sopenharmony_ci        delete clsHdcJdwpSimulator;
99cc290419Sopenharmony_ci        clsHdcJdwpSimulator = nullptr;
100cc290419Sopenharmony_ci    }
101cc290419Sopenharmony_ci    uv_stop(&loopMain);
102cc290419Sopenharmony_ci    TryCloseLoop(&loopMain, "Hdcjdwp test exit");
103cc290419Sopenharmony_ci    HiLog::Info(LABEL, "jdwp_test_process exit.");
104cc290419Sopenharmony_ci    PrintMessage("jdwp_test_process exit.");
105cc290419Sopenharmony_ci}
106cc290419Sopenharmony_ci
107cc290419Sopenharmony_cistatic void Stop(int signo)
108cc290419Sopenharmony_ci{
109cc290419Sopenharmony_ci    FreeInstance();
110cc290419Sopenharmony_ci    _exit(0);
111cc290419Sopenharmony_ci}
112cc290419Sopenharmony_ci
113cc290419Sopenharmony_ciint main(int argc, const char *argv[])
114cc290419Sopenharmony_ci{
115cc290419Sopenharmony_ci    uv_loop_init(&loopMain);
116cc290419Sopenharmony_ci
117cc290419Sopenharmony_ci    HiLog::Info(LABEL, "jdwp_test_process start.");
118cc290419Sopenharmony_ci    PrintMessage("jdwp_test_process start.");
119cc290419Sopenharmony_ci    if (signal(SIGINT, Stop) == SIG_ERR) {
120cc290419Sopenharmony_ci        PrintMessage("jdwp_test_process signal fail.");
121cc290419Sopenharmony_ci    }
122cc290419Sopenharmony_ci    clsHdcJdwpSimulator = new HdcJdwpSimulator(&loopMain, "com.example.myapplication");
123cc290419Sopenharmony_ci    if (!clsHdcJdwpSimulator->Connect()) {
124cc290419Sopenharmony_ci        PrintMessage("Connect fail.");
125cc290419Sopenharmony_ci        return -1;
126cc290419Sopenharmony_ci    }
127cc290419Sopenharmony_ci    uv_run(&loopMain, UV_RUN_DEFAULT);
128cc290419Sopenharmony_ci
129cc290419Sopenharmony_ci#ifdef JS_JDWP_CONNECT
130cc290419Sopenharmony_ci    PrintMessage("Enter 'exit' will stop the test.");
131cc290419Sopenharmony_ci    std::string line;
132cc290419Sopenharmony_ci    while (std::getline(std::cin, line)) {
133cc290419Sopenharmony_ci        if (!strcmp(line.c_str(), "exit")) {
134cc290419Sopenharmony_ci            PrintMessage("Exit current process.");
135cc290419Sopenharmony_ci            break;
136cc290419Sopenharmony_ci        }
137cc290419Sopenharmony_ci    }
138cc290419Sopenharmony_ci    FreeInstance();
139cc290419Sopenharmony_ci#endif // JS_JDWP_CONNECT
140cc290419Sopenharmony_ci    return 0;
141cc290419Sopenharmony_ci}