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