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#include "jdwp.h"
16cc290419Sopenharmony_ci#include <sys/eventfd.h>
17cc290419Sopenharmony_ci#include <thread>
18cc290419Sopenharmony_ci#include "system_depend.h"
19cc290419Sopenharmony_ci
20cc290419Sopenharmony_cinamespace Hdc {
21cc290419Sopenharmony_ciHdcJdwp::HdcJdwp(uv_loop_t *loopIn)
22cc290419Sopenharmony_ci{
23cc290419Sopenharmony_ci    listenPipe.data = this;
24cc290419Sopenharmony_ci    loop = loopIn;
25cc290419Sopenharmony_ci    refCount = 0;
26cc290419Sopenharmony_ci    uv_rwlock_init(&lockMapContext);
27cc290419Sopenharmony_ci    uv_rwlock_init(&lockJdwpTrack);
28cc290419Sopenharmony_ci    awakenPollFd = -1;
29cc290419Sopenharmony_ci    stop = false;
30cc290419Sopenharmony_ci}
31cc290419Sopenharmony_ci
32cc290419Sopenharmony_ciHdcJdwp::~HdcJdwp()
33cc290419Sopenharmony_ci{
34cc290419Sopenharmony_ci    Base::CloseFd(awakenPollFd);
35cc290419Sopenharmony_ci    uv_rwlock_destroy(&lockMapContext);
36cc290419Sopenharmony_ci    uv_rwlock_destroy(&lockJdwpTrack);
37cc290419Sopenharmony_ci}
38cc290419Sopenharmony_ci
39cc290419Sopenharmony_cibool HdcJdwp::ReadyForRelease()
40cc290419Sopenharmony_ci{
41cc290419Sopenharmony_ci    return refCount == 0;
42cc290419Sopenharmony_ci}
43cc290419Sopenharmony_ci
44cc290419Sopenharmony_civoid HdcJdwp::Stop()
45cc290419Sopenharmony_ci{
46cc290419Sopenharmony_ci    stop = true;
47cc290419Sopenharmony_ci    WakePollThread();
48cc290419Sopenharmony_ci    auto funcListenPipeClose = [](uv_handle_t *handle) -> void {
49cc290419Sopenharmony_ci        HdcJdwp *thisClass = (HdcJdwp *)handle->data;
50cc290419Sopenharmony_ci        --thisClass->refCount;
51cc290419Sopenharmony_ci    };
52cc290419Sopenharmony_ci    Base::TryCloseHandle((const uv_handle_t *)&listenPipe, funcListenPipeClose);
53cc290419Sopenharmony_ci    freeContextMutex.lock();
54cc290419Sopenharmony_ci    for (auto &&obj : mapCtxJdwp) {
55cc290419Sopenharmony_ci        HCtxJdwp v = obj.second;
56cc290419Sopenharmony_ci        FreeContext(v);
57cc290419Sopenharmony_ci    }
58cc290419Sopenharmony_ci    AdminContext(OP_CLEAR, 0, nullptr);
59cc290419Sopenharmony_ci    freeContextMutex.unlock();
60cc290419Sopenharmony_ci}
61cc290419Sopenharmony_ci
62cc290419Sopenharmony_civoid *HdcJdwp::MallocContext()
63cc290419Sopenharmony_ci{
64cc290419Sopenharmony_ci    HCtxJdwp ctx = nullptr;
65cc290419Sopenharmony_ci    if ((ctx = new ContextJdwp()) == nullptr) {
66cc290419Sopenharmony_ci        return nullptr;
67cc290419Sopenharmony_ci    }
68cc290419Sopenharmony_ci    ctx->isDebug = 0;
69cc290419Sopenharmony_ci    ctx->thisClass = this;
70cc290419Sopenharmony_ci    ctx->pipe.data = ctx;
71cc290419Sopenharmony_ci    ++refCount;
72cc290419Sopenharmony_ci    return ctx;
73cc290419Sopenharmony_ci}
74cc290419Sopenharmony_ci
75cc290419Sopenharmony_ci// Single thread, two parameters can be used
76cc290419Sopenharmony_civoid HdcJdwp::FreeContext(HCtxJdwp ctx)
77cc290419Sopenharmony_ci{
78cc290419Sopenharmony_ci    if (ctx->finish) {
79cc290419Sopenharmony_ci        return;
80cc290419Sopenharmony_ci    }
81cc290419Sopenharmony_ci    ctx->finish = true;
82cc290419Sopenharmony_ci    WRITE_LOG(LOG_INFO, "FreeContext for targetPID :%d", ctx->pid);
83cc290419Sopenharmony_ci    if (!stop) {
84cc290419Sopenharmony_ci        AdminContext(OP_REMOVE, ctx->pid, nullptr);
85cc290419Sopenharmony_ci    }
86cc290419Sopenharmony_ci    auto funcReqClose = [](uv_idle_t *handle) -> void {
87cc290419Sopenharmony_ci        HCtxJdwp ctxIn = (HCtxJdwp)handle->data;
88cc290419Sopenharmony_ci        --ctxIn->thisClass->refCount;
89cc290419Sopenharmony_ci        Base::TryCloseHandle((uv_handle_t *)handle, Base::CloseIdleCallback);
90cc290419Sopenharmony_ci
91cc290419Sopenharmony_ci        Base::TryCloseHandle((const uv_handle_t *)&ctxIn->pipe, [](uv_handle_t *handle) {
92cc290419Sopenharmony_ci            HCtxJdwp ctxIn = (HCtxJdwp)handle->data;
93cc290419Sopenharmony_ci#ifndef HDC_EMULATOR
94cc290419Sopenharmony_ci            if (ctxIn != nullptr) {
95cc290419Sopenharmony_ci                delete ctxIn;
96cc290419Sopenharmony_ci                ctxIn = nullptr;
97cc290419Sopenharmony_ci            }
98cc290419Sopenharmony_ci#endif
99cc290419Sopenharmony_ci        });
100cc290419Sopenharmony_ci    };
101cc290419Sopenharmony_ci    Base::IdleUvTask(loop, ctx, funcReqClose);
102cc290419Sopenharmony_ci}
103cc290419Sopenharmony_ci
104cc290419Sopenharmony_civoid HdcJdwp::RemoveFdFromPollList(uint32_t pid)
105cc290419Sopenharmony_ci{
106cc290419Sopenharmony_ci    for (auto &&pair : pollNodeMap) {
107cc290419Sopenharmony_ci        if (pair.second.ppid == pid) {
108cc290419Sopenharmony_ci            WRITE_LOG(LOG_INFO, "RemoveFdFromPollList for pid:%d.", pid);
109cc290419Sopenharmony_ci            pollNodeMap.erase(pair.second.pollfd.fd);
110cc290419Sopenharmony_ci            break;
111cc290419Sopenharmony_ci        }
112cc290419Sopenharmony_ci    }
113cc290419Sopenharmony_ci}
114cc290419Sopenharmony_ci
115cc290419Sopenharmony_civoid HdcJdwp::ReadStream(uv_stream_t *pipe, ssize_t nread, const uv_buf_t *buf)
116cc290419Sopenharmony_ci{
117cc290419Sopenharmony_ci    static std::once_flag firstLog;
118cc290419Sopenharmony_ci    std::call_once(firstLog, [&]() { SystemDepend::SetDevItem("persist.hdc.jdwp", "0"); });
119cc290419Sopenharmony_ci
120cc290419Sopenharmony_ci    bool ret = true;
121cc290419Sopenharmony_ci    if (nread == UV_ENOBUFS) {  // It is definite enough, usually only 4 bytes
122cc290419Sopenharmony_ci        ret = false;
123cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "HdcJdwp::ReadStream IOBuf max");
124cc290419Sopenharmony_ci    } else if (nread == 0) {
125cc290419Sopenharmony_ci        return;
126cc290419Sopenharmony_ci#ifdef JS_JDWP_CONNECT
127cc290419Sopenharmony_ci    } else if (nread < signed(JS_PKG_MIN_SIZE + sizeof(JsMsgHeader)) ||
128cc290419Sopenharmony_ci               nread > signed(JS_PKG_MAX_SIZE + sizeof(JsMsgHeader))) {
129cc290419Sopenharmony_ci#else
130cc290419Sopenharmony_ci    } else if (nread < 0 || nread != 4) {  // 4 : 4 bytes
131cc290419Sopenharmony_ci#endif  // JS_JDWP_CONNECT
132cc290419Sopenharmony_ci        ret = false;
133cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "HdcJdwp::ReadStream invalid package nread:%d.", nread);
134cc290419Sopenharmony_ci    }
135cc290419Sopenharmony_ci
136cc290419Sopenharmony_ci    HCtxJdwp ctxJdwp = static_cast<HCtxJdwp>(pipe->data);
137cc290419Sopenharmony_ci    HdcJdwp *thisClass = static_cast<HdcJdwp *>(ctxJdwp->thisClass);
138cc290419Sopenharmony_ci    if (ret) {
139cc290419Sopenharmony_ci        uint32_t pid = 0;
140cc290419Sopenharmony_ci        char *p = ctxJdwp->buf;
141cc290419Sopenharmony_ci        if (nread == sizeof(uint32_t)) {  // Java: pid
142cc290419Sopenharmony_ci            pid = atoi(p);
143cc290419Sopenharmony_ci        } else {  // JS:pid PkgName
144cc290419Sopenharmony_ci#ifdef JS_JDWP_CONNECT
145cc290419Sopenharmony_ci            // pid isDebug pkgName/processName
146cc290419Sopenharmony_ci            struct JsMsgHeader *jsMsg = reinterpret_cast<struct JsMsgHeader *>(p);
147cc290419Sopenharmony_ci            if (jsMsg->msgLen == nread) {
148cc290419Sopenharmony_ci                pid = jsMsg->pid;
149cc290419Sopenharmony_ci                string pkgName = string((char *)p + sizeof(JsMsgHeader), jsMsg->msgLen - sizeof(JsMsgHeader));
150cc290419Sopenharmony_ci                ctxJdwp->pkgName = pkgName;
151cc290419Sopenharmony_ci                ctxJdwp->isDebug = jsMsg->isDebug;
152cc290419Sopenharmony_ci            } else {
153cc290419Sopenharmony_ci                ret = false;
154cc290419Sopenharmony_ci                WRITE_LOG(LOG_DEBUG, "HdcJdwp::ReadStream invalid js package size %d:%d.", jsMsg->msgLen, nread);
155cc290419Sopenharmony_ci            }
156cc290419Sopenharmony_ci#endif  // JS_JDWP_CONNECT
157cc290419Sopenharmony_ci        }
158cc290419Sopenharmony_ci        if (pid > 0) {
159cc290419Sopenharmony_ci            ctxJdwp->pid = pid;
160cc290419Sopenharmony_ci#ifdef JS_JDWP_CONNECT
161cc290419Sopenharmony_ci            WRITE_LOG(LOG_DEBUG, "JDWP accept pid:%d-pkg:%s isDebug:%d",
162cc290419Sopenharmony_ci                pid, ctxJdwp->pkgName.c_str(), ctxJdwp->isDebug);
163cc290419Sopenharmony_ci#else
164cc290419Sopenharmony_ci            WRITE_LOG(LOG_DEBUG, "JDWP accept pid:%d", pid);
165cc290419Sopenharmony_ci#endif  // JS_JDWP_CONNECT
166cc290419Sopenharmony_ci            thisClass->AdminContext(OP_ADD, pid, ctxJdwp);
167cc290419Sopenharmony_ci            ret = true;
168cc290419Sopenharmony_ci            int fd = -1;
169cc290419Sopenharmony_ci            if (uv_fileno(reinterpret_cast<uv_handle_t *>(&(ctxJdwp->pipe)), &fd) < 0) {
170cc290419Sopenharmony_ci                WRITE_LOG(LOG_DEBUG, "HdcJdwp::ReadStream uv_fileno fail.");
171cc290419Sopenharmony_ci            } else {
172cc290419Sopenharmony_ci                thisClass->freeContextMutex.lock();
173cc290419Sopenharmony_ci                thisClass->pollNodeMap.emplace(fd, PollNode(fd, pid));
174cc290419Sopenharmony_ci                thisClass->freeContextMutex.unlock();
175cc290419Sopenharmony_ci                thisClass->WakePollThread();
176cc290419Sopenharmony_ci            }
177cc290419Sopenharmony_ci        }
178cc290419Sopenharmony_ci    }
179cc290419Sopenharmony_ci    Base::ZeroArray(ctxJdwp->buf);
180cc290419Sopenharmony_ci    if (!ret) {
181cc290419Sopenharmony_ci        WRITE_LOG(LOG_INFO, "ReadStream proc:%d err, free it.", ctxJdwp->pid);
182cc290419Sopenharmony_ci        thisClass->freeContextMutex.lock();
183cc290419Sopenharmony_ci        thisClass->FreeContext(ctxJdwp);
184cc290419Sopenharmony_ci        thisClass->freeContextMutex.unlock();
185cc290419Sopenharmony_ci    }
186cc290419Sopenharmony_ci}
187cc290419Sopenharmony_ci
188cc290419Sopenharmony_ci#ifdef JS_JDWP_CONNECT
189cc290419Sopenharmony_cistring HdcJdwp::GetProcessListExtendPkgName(uint8_t dr)
190cc290419Sopenharmony_ci{
191cc290419Sopenharmony_ci    constexpr uint8_t releaseApp = 2;
192cc290419Sopenharmony_ci    constexpr uint8_t allAppWithDr = 3;
193cc290419Sopenharmony_ci    string ret;
194cc290419Sopenharmony_ci    uv_rwlock_rdlock(&lockMapContext);
195cc290419Sopenharmony_ci    for (auto &&v : mapCtxJdwp) {
196cc290419Sopenharmony_ci        HCtxJdwp hj = v.second;
197cc290419Sopenharmony_ci        if (dr == 0) {
198cc290419Sopenharmony_ci            // allApp
199cc290419Sopenharmony_ci            ret += std::to_string(v.first) + " " + hj->pkgName + "\n";
200cc290419Sopenharmony_ci        } else if (dr == 1) {
201cc290419Sopenharmony_ci            // debugApp
202cc290419Sopenharmony_ci            if (hj->isDebug) {
203cc290419Sopenharmony_ci                ret += std::to_string(v.first) + " " + hj->pkgName + "\n";
204cc290419Sopenharmony_ci            }
205cc290419Sopenharmony_ci        } else if (dr == releaseApp) {
206cc290419Sopenharmony_ci            // releaseApp
207cc290419Sopenharmony_ci            if (!hj->isDebug) {
208cc290419Sopenharmony_ci                ret += std::to_string(v.first) + " " + hj->pkgName + "\n";
209cc290419Sopenharmony_ci            }
210cc290419Sopenharmony_ci        } else if (dr == allAppWithDr) {
211cc290419Sopenharmony_ci            // allApp with display debug or release
212cc290419Sopenharmony_ci            string apptype = "release";
213cc290419Sopenharmony_ci            if (hj->isDebug) {
214cc290419Sopenharmony_ci                apptype = "debug";
215cc290419Sopenharmony_ci            }
216cc290419Sopenharmony_ci            ret += std::to_string(v.first) + " " + hj->pkgName + " " + apptype + "\n";
217cc290419Sopenharmony_ci        }
218cc290419Sopenharmony_ci    }
219cc290419Sopenharmony_ci    uv_rwlock_rdunlock(&lockMapContext);
220cc290419Sopenharmony_ci    return ret;
221cc290419Sopenharmony_ci}
222cc290419Sopenharmony_ci#endif  // JS_JDWP_CONNECT
223cc290419Sopenharmony_ci
224cc290419Sopenharmony_civoid HdcJdwp::AcceptClient(uv_stream_t *server, int status)
225cc290419Sopenharmony_ci{
226cc290419Sopenharmony_ci    uv_pipe_t *listenPipe = (uv_pipe_t *)server;
227cc290419Sopenharmony_ci    HdcJdwp *thisClass = (HdcJdwp *)listenPipe->data;
228cc290419Sopenharmony_ci    HCtxJdwp ctxJdwp = (HCtxJdwp)thisClass->MallocContext();
229cc290419Sopenharmony_ci    if (!ctxJdwp) {
230cc290419Sopenharmony_ci        return;
231cc290419Sopenharmony_ci    }
232cc290419Sopenharmony_ci    uv_pipe_init(thisClass->loop, &ctxJdwp->pipe, 1);
233cc290419Sopenharmony_ci    if (uv_accept(server, (uv_stream_t *)&ctxJdwp->pipe) < 0) {
234cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "uv_accept failed");
235cc290419Sopenharmony_ci        thisClass->freeContextMutex.lock();
236cc290419Sopenharmony_ci        thisClass->FreeContext(ctxJdwp);
237cc290419Sopenharmony_ci        thisClass->freeContextMutex.unlock();
238cc290419Sopenharmony_ci        return;
239cc290419Sopenharmony_ci    }
240cc290419Sopenharmony_ci    auto funAlloc = [](uv_handle_t *handle, size_t sizeSuggested, uv_buf_t *buf) -> void {
241cc290419Sopenharmony_ci        HCtxJdwp ctxJdwp = (HCtxJdwp)handle->data;
242cc290419Sopenharmony_ci        buf->base = (char *)ctxJdwp->buf;
243cc290419Sopenharmony_ci        buf->len = sizeof(ctxJdwp->buf);
244cc290419Sopenharmony_ci    };
245cc290419Sopenharmony_ci    uv_read_start((uv_stream_t *)&ctxJdwp->pipe, funAlloc, ReadStream);
246cc290419Sopenharmony_ci}
247cc290419Sopenharmony_ci
248cc290419Sopenharmony_ci// Test bash connnet(UNIX-domain sockets):nc -U path/ohjpid-control < hexpid.file
249cc290419Sopenharmony_ci// Test uv connect(pipe): 'uv_pipe_connect'
250cc290419Sopenharmony_cibool HdcJdwp::JdwpListen()
251cc290419Sopenharmony_ci{
252cc290419Sopenharmony_ci#ifdef HDC_PCDEBUG
253cc290419Sopenharmony_ci    // if test, can be enabled
254cc290419Sopenharmony_ci    return true;
255cc290419Sopenharmony_ci    const char jdwpCtrlName[] = { 'o', 'h', 'j', 'p', 'i', 'd', '-', 'c', 'o', 'n', 't', 'r', 'o', 'l', 0 };
256cc290419Sopenharmony_ci    unlink(jdwpCtrlName);
257cc290419Sopenharmony_ci#else
258cc290419Sopenharmony_ci    const char jdwpCtrlName[] = { '\0', 'o', 'h', 'j', 'p', 'i', 'd', '-', 'c', 'o', 'n', 't', 'r', 'o', 'l', 0 };
259cc290419Sopenharmony_ci#endif
260cc290419Sopenharmony_ci    const int DEFAULT_BACKLOG = 4;
261cc290419Sopenharmony_ci    bool ret = false;
262cc290419Sopenharmony_ci    while (true) {
263cc290419Sopenharmony_ci        uv_pipe_init(loop, &listenPipe, 0);
264cc290419Sopenharmony_ci        listenPipe.data = this;
265cc290419Sopenharmony_ci        if (UvPipeBind(&listenPipe, jdwpCtrlName, sizeof(jdwpCtrlName))) {
266cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "UvPipeBind failed");
267cc290419Sopenharmony_ci            return ret;
268cc290419Sopenharmony_ci        }
269cc290419Sopenharmony_ci        if (uv_listen((uv_stream_t *)&listenPipe, DEFAULT_BACKLOG, AcceptClient)) {
270cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "uv_listen failed");
271cc290419Sopenharmony_ci            break;
272cc290419Sopenharmony_ci        }
273cc290419Sopenharmony_ci        ++refCount;
274cc290419Sopenharmony_ci        ret = true;
275cc290419Sopenharmony_ci        break;
276cc290419Sopenharmony_ci    }
277cc290419Sopenharmony_ci    // listenPipe close by stop
278cc290419Sopenharmony_ci    return ret;
279cc290419Sopenharmony_ci}
280cc290419Sopenharmony_ci
281cc290419Sopenharmony_ciint HdcJdwp::UvPipeBind(uv_pipe_t* handle, const char* name, size_t size)
282cc290419Sopenharmony_ci{
283cc290419Sopenharmony_ci    char buffer[BUF_SIZE_DEFAULT] = { 0 };
284cc290419Sopenharmony_ci
285cc290419Sopenharmony_ci    if (handle->io_watcher.fd >= 0) {
286cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "socket already bound %d", handle->io_watcher.fd);
287cc290419Sopenharmony_ci        return -1;
288cc290419Sopenharmony_ci    }
289cc290419Sopenharmony_ci
290cc290419Sopenharmony_ci    int type = SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC;
291cc290419Sopenharmony_ci    int sockfd = socket(AF_UNIX, type, 0);
292cc290419Sopenharmony_ci    if (sockfd < 0) {
293cc290419Sopenharmony_ci        strerror_r(errno, buffer, BUF_SIZE_DEFAULT);
294cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "socket failed errno:%d %s", errno, buffer);
295cc290419Sopenharmony_ci        return -1;
296cc290419Sopenharmony_ci    }
297cc290419Sopenharmony_ci
298cc290419Sopenharmony_ci#if defined(SO_NOSIGPIPE)
299cc290419Sopenharmony_ci    int on = 1;
300cc290419Sopenharmony_ci    setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on));
301cc290419Sopenharmony_ci#endif
302cc290419Sopenharmony_ci
303cc290419Sopenharmony_ci    struct sockaddr_un saddr;
304cc290419Sopenharmony_ci    Base::ZeroStruct(saddr);
305cc290419Sopenharmony_ci    size_t capacity = sizeof(saddr.sun_path);
306cc290419Sopenharmony_ci    size_t min = size < capacity ? size : capacity;
307cc290419Sopenharmony_ci    for (size_t i = 0; i < min; i++) {
308cc290419Sopenharmony_ci        saddr.sun_path[i] = name[i];
309cc290419Sopenharmony_ci    }
310cc290419Sopenharmony_ci    saddr.sun_path[capacity - 1] = '\0';
311cc290419Sopenharmony_ci    saddr.sun_family = AF_UNIX;
312cc290419Sopenharmony_ci    size_t saddrLen = sizeof(saddr.sun_family) + size - 1;
313cc290419Sopenharmony_ci    int err = bind(sockfd, reinterpret_cast<struct sockaddr*>(&saddr), saddrLen);
314cc290419Sopenharmony_ci    if (err != 0) {
315cc290419Sopenharmony_ci        strerror_r(errno, buffer, BUF_SIZE_DEFAULT);
316cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "bind failed errno:%d %s", errno, buffer);
317cc290419Sopenharmony_ci        close(sockfd);
318cc290419Sopenharmony_ci        return -1;
319cc290419Sopenharmony_ci    }
320cc290419Sopenharmony_ci    constexpr uint32_t uvHandleBound = 0x00002000;
321cc290419Sopenharmony_ci    handle->flags |= uvHandleBound;
322cc290419Sopenharmony_ci    handle->io_watcher.fd = sockfd;
323cc290419Sopenharmony_ci    return 0;
324cc290419Sopenharmony_ci}
325cc290419Sopenharmony_ci
326cc290419Sopenharmony_ci// Working in the main thread, but will be accessed by each session thread, so we need to set thread lock
327cc290419Sopenharmony_civoid *HdcJdwp::AdminContext(const uint8_t op, const uint32_t pid, HCtxJdwp ctxJdwp)
328cc290419Sopenharmony_ci{
329cc290419Sopenharmony_ci    HCtxJdwp hRet = nullptr;
330cc290419Sopenharmony_ci    switch (op) {
331cc290419Sopenharmony_ci        case OP_ADD: {
332cc290419Sopenharmony_ci            uv_rwlock_wrlock(&lockMapContext);
333cc290419Sopenharmony_ci            const int maxMapSize = 1024;
334cc290419Sopenharmony_ci            if (mapCtxJdwp.size() < maxMapSize) {
335cc290419Sopenharmony_ci                mapCtxJdwp[pid] = ctxJdwp;
336cc290419Sopenharmony_ci            }
337cc290419Sopenharmony_ci            uv_rwlock_wrunlock(&lockMapContext);
338cc290419Sopenharmony_ci            break;
339cc290419Sopenharmony_ci        }
340cc290419Sopenharmony_ci        case OP_REMOVE:
341cc290419Sopenharmony_ci            uv_rwlock_wrlock(&lockMapContext);
342cc290419Sopenharmony_ci            mapCtxJdwp.erase(pid);
343cc290419Sopenharmony_ci            RemoveFdFromPollList(pid);
344cc290419Sopenharmony_ci            uv_rwlock_wrunlock(&lockMapContext);
345cc290419Sopenharmony_ci            break;
346cc290419Sopenharmony_ci        case OP_QUERY: {
347cc290419Sopenharmony_ci            uv_rwlock_rdlock(&lockMapContext);
348cc290419Sopenharmony_ci            if (mapCtxJdwp.count(pid)) {
349cc290419Sopenharmony_ci                hRet = mapCtxJdwp[pid];
350cc290419Sopenharmony_ci            }
351cc290419Sopenharmony_ci            uv_rwlock_rdunlock(&lockMapContext);
352cc290419Sopenharmony_ci            break;
353cc290419Sopenharmony_ci        }
354cc290419Sopenharmony_ci        case OP_CLEAR: {
355cc290419Sopenharmony_ci            uv_rwlock_wrlock(&lockMapContext);
356cc290419Sopenharmony_ci            mapCtxJdwp.clear();
357cc290419Sopenharmony_ci            pollNodeMap.clear();
358cc290419Sopenharmony_ci            uv_rwlock_wrunlock(&lockMapContext);
359cc290419Sopenharmony_ci            break;
360cc290419Sopenharmony_ci        }
361cc290419Sopenharmony_ci        default:
362cc290419Sopenharmony_ci            break;
363cc290419Sopenharmony_ci    }
364cc290419Sopenharmony_ci    if (op == OP_ADD || op == OP_REMOVE || op == OP_CLEAR) {
365cc290419Sopenharmony_ci        uv_rwlock_wrlock(&lockJdwpTrack);
366cc290419Sopenharmony_ci        ProcessListUpdated();
367cc290419Sopenharmony_ci        uv_rwlock_wrunlock(&lockJdwpTrack);
368cc290419Sopenharmony_ci    }
369cc290419Sopenharmony_ci    return hRet;
370cc290419Sopenharmony_ci}
371cc290419Sopenharmony_ci
372cc290419Sopenharmony_ci// work on main thread
373cc290419Sopenharmony_civoid HdcJdwp::SendCallbackJdwpNewFD(uv_write_t *req, int status)
374cc290419Sopenharmony_ci{
375cc290419Sopenharmony_ci    // It usually works successful, not notify session work
376cc290419Sopenharmony_ci    HCtxJdwp ctx = (HCtxJdwp)req->data;
377cc290419Sopenharmony_ci    if (status >= 0) {
378cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "SendCallbackJdwpNewFD successful %d, active jdwp forward", ctx->pid);
379cc290419Sopenharmony_ci    } else {
380cc290419Sopenharmony_ci        WRITE_LOG(LOG_WARN, "SendCallbackJdwpNewFD failed %d", ctx->pid);
381cc290419Sopenharmony_ci    }
382cc290419Sopenharmony_ci    delete req;
383cc290419Sopenharmony_ci}
384cc290419Sopenharmony_ci
385cc290419Sopenharmony_ci// Each session calls the interface through the main thread message queue, which cannot be called directly across
386cc290419Sopenharmony_ci// threads
387cc290419Sopenharmony_ci// work on main thread
388cc290419Sopenharmony_cibool HdcJdwp::SendJdwpNewFD(uint32_t targetPID, int fd)
389cc290419Sopenharmony_ci{
390cc290419Sopenharmony_ci    bool ret = false;
391cc290419Sopenharmony_ci    while (true) {
392cc290419Sopenharmony_ci        HCtxJdwp ctx = (HCtxJdwp)AdminContext(OP_QUERY, targetPID, nullptr);
393cc290419Sopenharmony_ci        if (!ctx) {
394cc290419Sopenharmony_ci            break;
395cc290419Sopenharmony_ci        }
396cc290419Sopenharmony_ci        ctx->dummy = static_cast<uint8_t>('!');
397cc290419Sopenharmony_ci        if (uv_tcp_init(loop, &ctx->jvmTCP)) {
398cc290419Sopenharmony_ci            break;
399cc290419Sopenharmony_ci        }
400cc290419Sopenharmony_ci        if (uv_tcp_open(&ctx->jvmTCP, fd)) {
401cc290419Sopenharmony_ci            break;
402cc290419Sopenharmony_ci        }
403cc290419Sopenharmony_ci        // transfer fd to jvm
404cc290419Sopenharmony_ci        // clang-format off
405cc290419Sopenharmony_ci        if (Base::SendToStreamEx((uv_stream_t *)&ctx->pipe, (uint8_t *)&ctx->dummy, 1, (uv_stream_t *)&ctx->jvmTCP,
406cc290419Sopenharmony_ci            (void *)SendCallbackJdwpNewFD, (const void *)ctx) < 0) {
407cc290419Sopenharmony_ci            break;
408cc290419Sopenharmony_ci        }
409cc290419Sopenharmony_ci        // clang-format on
410cc290419Sopenharmony_ci        ++refCount;
411cc290419Sopenharmony_ci        ret = true;
412cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "SendJdwpNewFD successful targetPID:%d fd%d", targetPID, fd);
413cc290419Sopenharmony_ci        break;
414cc290419Sopenharmony_ci    }
415cc290419Sopenharmony_ci    return ret;
416cc290419Sopenharmony_ci}
417cc290419Sopenharmony_ci
418cc290419Sopenharmony_cibool HdcJdwp::SendArkNewFD(const std::string str, int fd)
419cc290419Sopenharmony_ci{
420cc290419Sopenharmony_ci    bool ret = false;
421cc290419Sopenharmony_ci    while (true) {
422cc290419Sopenharmony_ci        // str(ark:pid@tid@Debugger)
423cc290419Sopenharmony_ci        size_t pos = str.find_first_of(':');
424cc290419Sopenharmony_ci        std::string right = str.substr(pos + 1);
425cc290419Sopenharmony_ci        pos = right.find_first_of("@");
426cc290419Sopenharmony_ci        std::string pidstr = right.substr(0, pos);
427cc290419Sopenharmony_ci        uint32_t pid = static_cast<uint32_t>(std::atoi(pidstr.c_str()));
428cc290419Sopenharmony_ci        HCtxJdwp ctx = (HCtxJdwp)AdminContext(OP_QUERY, pid, nullptr);
429cc290419Sopenharmony_ci        if (!ctx) {
430cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "SendArkNewFD query pid:%u failed", pid);
431cc290419Sopenharmony_ci            break;
432cc290419Sopenharmony_ci        }
433cc290419Sopenharmony_ci        uint32_t size = sizeof(int32_t) + str.size();
434cc290419Sopenharmony_ci        // fd | str(ark:pid@tid@Debugger)
435cc290419Sopenharmony_ci        uint8_t buf[size];
436cc290419Sopenharmony_ci        if (memcpy_s(buf, sizeof(int32_t), &fd, sizeof(int32_t)) != EOK) {
437cc290419Sopenharmony_ci            WRITE_LOG(LOG_WARN, "From fd Create buf failed, fd:%d", fd);
438cc290419Sopenharmony_ci            return false;
439cc290419Sopenharmony_ci        }
440cc290419Sopenharmony_ci        if (memcpy_s(buf + sizeof(int32_t), str.size(), str.c_str(), str.size()) != EOK) {
441cc290419Sopenharmony_ci            WRITE_LOG(LOG_WARN, "SendArkNewFD failed fd:%d str:%s", fd, str.c_str());
442cc290419Sopenharmony_ci            return false;
443cc290419Sopenharmony_ci        }
444cc290419Sopenharmony_ci        uv_stream_t *stream = (uv_stream_t *)&ctx->pipe;
445cc290419Sopenharmony_ci        SendFdToApp(stream->io_watcher.fd, buf, size, fd);
446cc290419Sopenharmony_ci        ret = true;
447cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "SendArkNewFD successful str:%s fd%d", str.c_str(), fd);
448cc290419Sopenharmony_ci        Base::CloseFd(fd);
449cc290419Sopenharmony_ci        break;
450cc290419Sopenharmony_ci    }
451cc290419Sopenharmony_ci    return ret;
452cc290419Sopenharmony_ci}
453cc290419Sopenharmony_ci
454cc290419Sopenharmony_cibool HdcJdwp::SendFdToApp(int sockfd, uint8_t *buf, int size, int fd)
455cc290419Sopenharmony_ci{
456cc290419Sopenharmony_ci    struct iovec iov;
457cc290419Sopenharmony_ci    iov.iov_base = buf;
458cc290419Sopenharmony_ci    iov.iov_len = static_cast<unsigned int>(size);
459cc290419Sopenharmony_ci    struct msghdr msg;
460cc290419Sopenharmony_ci    msg.msg_name = nullptr;
461cc290419Sopenharmony_ci    msg.msg_namelen = 0;
462cc290419Sopenharmony_ci    msg.msg_iov = &iov;
463cc290419Sopenharmony_ci    msg.msg_iovlen = 1;
464cc290419Sopenharmony_ci
465cc290419Sopenharmony_ci    int len = CMSG_SPACE(static_cast<unsigned int>(sizeof(fd)));
466cc290419Sopenharmony_ci    char ctlBuf[len];
467cc290419Sopenharmony_ci    msg.msg_control = ctlBuf;
468cc290419Sopenharmony_ci    msg.msg_controllen = sizeof(ctlBuf);
469cc290419Sopenharmony_ci
470cc290419Sopenharmony_ci    struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
471cc290419Sopenharmony_ci    if (cmsg == nullptr) {
472cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "SendFdToApp cmsg is nullptr");
473cc290419Sopenharmony_ci        return false;
474cc290419Sopenharmony_ci    }
475cc290419Sopenharmony_ci    cmsg->cmsg_level = SOL_SOCKET;
476cc290419Sopenharmony_ci    cmsg->cmsg_type = SCM_RIGHTS;
477cc290419Sopenharmony_ci    cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
478cc290419Sopenharmony_ci    if (memcpy_s(CMSG_DATA(cmsg), sizeof(fd), &fd, sizeof(fd)) != 0) {
479cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "SendFdToApp memcpy error:%d", errno);
480cc290419Sopenharmony_ci        return false;
481cc290419Sopenharmony_ci    }
482cc290419Sopenharmony_ci    if (sendmsg(sockfd, &msg, 0) < 0) {
483cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "SendFdToApp sendmsg errno:%d", errno);
484cc290419Sopenharmony_ci        return false;
485cc290419Sopenharmony_ci    }
486cc290419Sopenharmony_ci    return true;
487cc290419Sopenharmony_ci}
488cc290419Sopenharmony_ci
489cc290419Sopenharmony_ci// cross thread call begin
490cc290419Sopenharmony_cibool HdcJdwp::CheckPIDExist(uint32_t targetPID)
491cc290419Sopenharmony_ci{
492cc290419Sopenharmony_ci    HCtxJdwp ctx = (HCtxJdwp)AdminContext(OP_QUERY, targetPID, nullptr);
493cc290419Sopenharmony_ci    return ctx != nullptr;
494cc290419Sopenharmony_ci}
495cc290419Sopenharmony_ci
496cc290419Sopenharmony_cistring HdcJdwp::GetProcessList()
497cc290419Sopenharmony_ci{
498cc290419Sopenharmony_ci    string ret;
499cc290419Sopenharmony_ci    uv_rwlock_rdlock(&lockMapContext);
500cc290419Sopenharmony_ci    for (auto &&v : mapCtxJdwp) {
501cc290419Sopenharmony_ci        ret += std::to_string(v.first) + "\n";
502cc290419Sopenharmony_ci    }
503cc290419Sopenharmony_ci    uv_rwlock_rdunlock(&lockMapContext);
504cc290419Sopenharmony_ci    return ret;
505cc290419Sopenharmony_ci}
506cc290419Sopenharmony_ci// cross thread call finish
507cc290419Sopenharmony_ci
508cc290419Sopenharmony_cisize_t HdcJdwp::JdwpProcessListMsg(char *buffer, size_t bufferlen, uint8_t dr)
509cc290419Sopenharmony_ci{
510cc290419Sopenharmony_ci    // Message is length-prefixed with 4 hex digits in ASCII.
511cc290419Sopenharmony_ci    static constexpr size_t headerLen = 5;
512cc290419Sopenharmony_ci    char head[headerLen + 2];
513cc290419Sopenharmony_ci#ifdef JS_JDWP_CONNECT
514cc290419Sopenharmony_ci    string result = GetProcessListExtendPkgName(dr);
515cc290419Sopenharmony_ci#else
516cc290419Sopenharmony_ci    string result = GetProcessList();
517cc290419Sopenharmony_ci#endif // JS_JDWP_CONNECT
518cc290419Sopenharmony_ci
519cc290419Sopenharmony_ci    size_t len = result.length();
520cc290419Sopenharmony_ci    if (bufferlen < (len + headerLen)) {
521cc290419Sopenharmony_ci        WRITE_LOG(LOG_WARN, "truncating JDWP process list (max len = %zu) ", bufferlen);
522cc290419Sopenharmony_ci        len = bufferlen;
523cc290419Sopenharmony_ci    }
524cc290419Sopenharmony_ci    if (snprintf_s(head, sizeof head, sizeof head - 1, "%04zx\n", len) < 0) {
525cc290419Sopenharmony_ci        WRITE_LOG(LOG_WARN, " JdwpProcessListMsg head fail.");
526cc290419Sopenharmony_ci        return 0;
527cc290419Sopenharmony_ci    }
528cc290419Sopenharmony_ci    if (memcpy_s(buffer, bufferlen, head, headerLen) != EOK) {
529cc290419Sopenharmony_ci        WRITE_LOG(LOG_WARN, " JdwpProcessListMsg get head fail.");
530cc290419Sopenharmony_ci        return 0;
531cc290419Sopenharmony_ci    }
532cc290419Sopenharmony_ci    if (memcpy_s(buffer + headerLen, (bufferlen - headerLen), result.c_str(), len) != EOK) {
533cc290419Sopenharmony_ci        WRITE_LOG(LOG_WARN, " JdwpProcessListMsg get data  fail.");
534cc290419Sopenharmony_ci        return 0;
535cc290419Sopenharmony_ci    }
536cc290419Sopenharmony_ci    return len + headerLen;
537cc290419Sopenharmony_ci}
538cc290419Sopenharmony_ci
539cc290419Sopenharmony_civoid HdcJdwp::SendProcessList(HTaskInfo t, string data)
540cc290419Sopenharmony_ci{
541cc290419Sopenharmony_ci    if (t == nullptr || data.size() == 0) {
542cc290419Sopenharmony_ci        WRITE_LOG(LOG_WARN, " SendProcessList, Nothing needs to be sent.");
543cc290419Sopenharmony_ci        return;
544cc290419Sopenharmony_ci    }
545cc290419Sopenharmony_ci    void *clsSession = t->ownerSessionClass;
546cc290419Sopenharmony_ci    HdcSessionBase *sessionBase = static_cast<HdcSessionBase *>(clsSession);
547cc290419Sopenharmony_ci    sessionBase->LogMsg(t->sessionId, t->channelId, MSG_OK, data.c_str());
548cc290419Sopenharmony_ci}
549cc290419Sopenharmony_ci
550cc290419Sopenharmony_civoid HdcJdwp::ProcessListUpdated(HTaskInfo task)
551cc290419Sopenharmony_ci{
552cc290419Sopenharmony_ci    if (jdwpTrackers.size() <= 0) {
553cc290419Sopenharmony_ci        return;
554cc290419Sopenharmony_ci    }
555cc290419Sopenharmony_ci#ifdef JS_JDWP_CONNECT
556cc290419Sopenharmony_ci    static constexpr uint32_t jpidTrackListSize = 1024 * 4;
557cc290419Sopenharmony_ci#else
558cc290419Sopenharmony_ci    static constexpr uint32_t jpidTrackListSize = 1024;
559cc290419Sopenharmony_ci#endif // JS_JDWP_CONNECT
560cc290419Sopenharmony_ci    std::string data;
561cc290419Sopenharmony_ci    if (task != nullptr) {
562cc290419Sopenharmony_ci        data.resize(jpidTrackListSize);
563cc290419Sopenharmony_ci        size_t len = JdwpProcessListMsg(&data[0], data.size(), task->debugRelease);
564cc290419Sopenharmony_ci        if (len > 0) {
565cc290419Sopenharmony_ci            data.resize(len);
566cc290419Sopenharmony_ci            SendProcessList(task, data);
567cc290419Sopenharmony_ci        }
568cc290419Sopenharmony_ci        return;
569cc290419Sopenharmony_ci    }
570cc290419Sopenharmony_ci    for (auto iter = jdwpTrackers.begin(); iter != jdwpTrackers.end();) {
571cc290419Sopenharmony_ci        if (*iter == nullptr) {
572cc290419Sopenharmony_ci            continue;
573cc290419Sopenharmony_ci        }
574cc290419Sopenharmony_ci        // The channel for the track-jpid has been stopped.
575cc290419Sopenharmony_ci        if ((*iter)->taskStop || (*iter)->taskFree || !(*iter)->taskClass) {
576cc290419Sopenharmony_ci            iter = jdwpTrackers.erase(remove(jdwpTrackers.begin(), jdwpTrackers.end(), *iter), jdwpTrackers.end());
577cc290419Sopenharmony_ci            if (jdwpTrackers.size() == 0) {
578cc290419Sopenharmony_ci                return;
579cc290419Sopenharmony_ci            }
580cc290419Sopenharmony_ci        } else {
581cc290419Sopenharmony_ci            data.resize(jpidTrackListSize);
582cc290419Sopenharmony_ci            size_t len = JdwpProcessListMsg(&data[0], data.size(), (*iter)->debugRelease);
583cc290419Sopenharmony_ci            if (len > 0) {
584cc290419Sopenharmony_ci                data.resize(len);
585cc290419Sopenharmony_ci                SendProcessList(*iter, data);
586cc290419Sopenharmony_ci            }
587cc290419Sopenharmony_ci            iter++;
588cc290419Sopenharmony_ci        }
589cc290419Sopenharmony_ci    }
590cc290419Sopenharmony_ci}
591cc290419Sopenharmony_ci
592cc290419Sopenharmony_cibool HdcJdwp::CreateJdwpTracker(HTaskInfo taskInfo)
593cc290419Sopenharmony_ci{
594cc290419Sopenharmony_ci    if (taskInfo == nullptr) {
595cc290419Sopenharmony_ci        return false;
596cc290419Sopenharmony_ci    }
597cc290419Sopenharmony_ci    uv_rwlock_wrlock(&lockJdwpTrack);
598cc290419Sopenharmony_ci    auto it = std::find(jdwpTrackers.begin(), jdwpTrackers.end(), taskInfo);
599cc290419Sopenharmony_ci    if (it == jdwpTrackers.end()) {
600cc290419Sopenharmony_ci        jdwpTrackers.push_back(taskInfo);
601cc290419Sopenharmony_ci    }
602cc290419Sopenharmony_ci    ProcessListUpdated(taskInfo);
603cc290419Sopenharmony_ci    uv_rwlock_wrunlock(&lockJdwpTrack);
604cc290419Sopenharmony_ci    return true;
605cc290419Sopenharmony_ci}
606cc290419Sopenharmony_ci
607cc290419Sopenharmony_civoid HdcJdwp::RemoveJdwpTracker(HTaskInfo taskInfo)
608cc290419Sopenharmony_ci{
609cc290419Sopenharmony_ci    if (taskInfo == nullptr) {
610cc290419Sopenharmony_ci        return;
611cc290419Sopenharmony_ci    }
612cc290419Sopenharmony_ci    uv_rwlock_wrlock(&lockJdwpTrack);
613cc290419Sopenharmony_ci    auto it = std::find(jdwpTrackers.begin(), jdwpTrackers.end(), taskInfo);
614cc290419Sopenharmony_ci    if (it != jdwpTrackers.end()) {
615cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "RemoveJdwpTracker channelId:%d, taskType:%d.", taskInfo->channelId, taskInfo->taskType);
616cc290419Sopenharmony_ci        jdwpTrackers.erase(remove(jdwpTrackers.begin(), jdwpTrackers.end(), *it), jdwpTrackers.end());
617cc290419Sopenharmony_ci    }
618cc290419Sopenharmony_ci    uv_rwlock_wrunlock(&lockJdwpTrack);
619cc290419Sopenharmony_ci}
620cc290419Sopenharmony_ci
621cc290419Sopenharmony_civoid HdcJdwp::DrainAwakenPollThread() const
622cc290419Sopenharmony_ci{
623cc290419Sopenharmony_ci    uint64_t value = 0;
624cc290419Sopenharmony_ci    ssize_t retVal = read(awakenPollFd, &value, sizeof(value));
625cc290419Sopenharmony_ci    if (retVal < 0) {
626cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "DrainAwakenPollThread: Failed to read data from awaken pipe %d", retVal);
627cc290419Sopenharmony_ci    }
628cc290419Sopenharmony_ci}
629cc290419Sopenharmony_ci
630cc290419Sopenharmony_civoid HdcJdwp::WakePollThread()
631cc290419Sopenharmony_ci{
632cc290419Sopenharmony_ci    if (awakenPollFd < 0) {
633cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "awakenPollFd: MUST initialized before notifying");
634cc290419Sopenharmony_ci        return;
635cc290419Sopenharmony_ci    }
636cc290419Sopenharmony_ci    static const uint64_t increment = 1;
637cc290419Sopenharmony_ci    ssize_t retVal = write(awakenPollFd, &increment, sizeof(increment));
638cc290419Sopenharmony_ci    if (retVal < 0) {
639cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "WakePollThread: Failed to write data into awaken pipe %d", retVal);
640cc290419Sopenharmony_ci    }
641cc290419Sopenharmony_ci}
642cc290419Sopenharmony_ci
643cc290419Sopenharmony_civoid *HdcJdwp::FdEventPollThread(void *args)
644cc290419Sopenharmony_ci{
645cc290419Sopenharmony_ci    auto thisClass = static_cast<HdcJdwp *>(args);
646cc290419Sopenharmony_ci    std::vector<struct pollfd> pollfds;
647cc290419Sopenharmony_ci    size_t size = 0;
648cc290419Sopenharmony_ci    while (!thisClass->stop) {
649cc290419Sopenharmony_ci        thisClass->freeContextMutex.lock();
650cc290419Sopenharmony_ci        if (size != thisClass->pollNodeMap.size() || thisClass->pollNodeMap.size() == 0) {
651cc290419Sopenharmony_ci            pollfds.clear();
652cc290419Sopenharmony_ci            struct pollfd pollFd;
653cc290419Sopenharmony_ci            for (const auto &pair : thisClass->pollNodeMap) {
654cc290419Sopenharmony_ci                pollFd.fd = pair.second.pollfd.fd;
655cc290419Sopenharmony_ci                pollFd.events = pair.second.pollfd.events;
656cc290419Sopenharmony_ci                pollFd.revents = pair.second.pollfd.revents;
657cc290419Sopenharmony_ci                pollfds.push_back(pollFd);
658cc290419Sopenharmony_ci            }
659cc290419Sopenharmony_ci            pollFd.fd = thisClass->awakenPollFd;
660cc290419Sopenharmony_ci            pollFd.events = POLLIN;
661cc290419Sopenharmony_ci            pollFd.revents = 0;
662cc290419Sopenharmony_ci            pollfds.push_back(pollFd);
663cc290419Sopenharmony_ci            size = pollfds.size();
664cc290419Sopenharmony_ci        }
665cc290419Sopenharmony_ci        thisClass->freeContextMutex.unlock();
666cc290419Sopenharmony_ci        poll(&pollfds[0], size, -1);
667cc290419Sopenharmony_ci        for (const auto &pollfdsing : pollfds) {
668cc290419Sopenharmony_ci            if (pollfdsing.revents & (POLLNVAL | POLLRDHUP | POLLHUP | POLLERR)) {  // POLLNVAL:fd not open
669cc290419Sopenharmony_ci                thisClass->freeContextMutex.lock();
670cc290419Sopenharmony_ci                auto it = thisClass->pollNodeMap.find(pollfdsing.fd);
671cc290419Sopenharmony_ci                if (it != thisClass->pollNodeMap.end()) {
672cc290419Sopenharmony_ci                    uint32_t targetPID = it->second.ppid;
673cc290419Sopenharmony_ci                    HCtxJdwp ctx = static_cast<HCtxJdwp>(thisClass->AdminContext(OP_QUERY, targetPID, nullptr));
674cc290419Sopenharmony_ci                    if (ctx != nullptr) {
675cc290419Sopenharmony_ci                        thisClass->AdminContext(OP_REMOVE, targetPID, nullptr);
676cc290419Sopenharmony_ci                    }
677cc290419Sopenharmony_ci                }
678cc290419Sopenharmony_ci                thisClass->freeContextMutex.unlock();
679cc290419Sopenharmony_ci            } else if (pollfdsing.revents & POLLIN) {
680cc290419Sopenharmony_ci                if (pollfdsing.fd == thisClass->awakenPollFd) {
681cc290419Sopenharmony_ci                    thisClass->DrainAwakenPollThread();
682cc290419Sopenharmony_ci                }
683cc290419Sopenharmony_ci            }
684cc290419Sopenharmony_ci        }
685cc290419Sopenharmony_ci    }
686cc290419Sopenharmony_ci    return nullptr;
687cc290419Sopenharmony_ci}
688cc290419Sopenharmony_ci
689cc290419Sopenharmony_ciint HdcJdwp::CreateFdEventPoll()
690cc290419Sopenharmony_ci{
691cc290419Sopenharmony_ci    pthread_t tid;
692cc290419Sopenharmony_ci    Base::CloseFd(awakenPollFd);
693cc290419Sopenharmony_ci    awakenPollFd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
694cc290419Sopenharmony_ci    if (awakenPollFd < 0) {
695cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "CreateFdEventPoll : Failed to create awakenPollFd");
696cc290419Sopenharmony_ci        return ERR_GENERIC;
697cc290419Sopenharmony_ci    }
698cc290419Sopenharmony_ci    int tret = pthread_create(&tid, nullptr, FdEventPollThread, this);
699cc290419Sopenharmony_ci    if (tret != 0) {
700cc290419Sopenharmony_ci        WRITE_LOG(LOG_INFO, "FdEventPollThread create fail.");
701cc290419Sopenharmony_ci        return tret;
702cc290419Sopenharmony_ci    }
703cc290419Sopenharmony_ci    return RET_SUCCESS;
704cc290419Sopenharmony_ci}
705cc290419Sopenharmony_ci
706cc290419Sopenharmony_ci// jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=8000
707cc290419Sopenharmony_ciint HdcJdwp::Initial()
708cc290419Sopenharmony_ci{
709cc290419Sopenharmony_ci    freeContextMutex.lock();
710cc290419Sopenharmony_ci    pollNodeMap.clear();
711cc290419Sopenharmony_ci    freeContextMutex.unlock();
712cc290419Sopenharmony_ci    if (!JdwpListen()) {
713cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "JdwpListen failed");
714cc290419Sopenharmony_ci        return ERR_MODULE_JDWP_FAILED;
715cc290419Sopenharmony_ci    }
716cc290419Sopenharmony_ci    SystemDepend::SetDevItem("persist.hdc.jdwp", "0");
717cc290419Sopenharmony_ci    SystemDepend::SetDevItem("persist.hdc.jdwp", "1");
718cc290419Sopenharmony_ci    if (CreateFdEventPoll() < 0) {
719cc290419Sopenharmony_ci        return ERR_MODULE_JDWP_FAILED;
720cc290419Sopenharmony_ci    }
721cc290419Sopenharmony_ci    return RET_SUCCESS;
722cc290419Sopenharmony_ci}
723cc290419Sopenharmony_ci}
724