// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. #include #include #include #include #include "bin/dbg_connection.h" #include "bin/fdutils.h" #include "bin/socket.h" int DebuggerConnectionImpl::epoll_fd_ = -1; int DebuggerConnectionImpl::wakeup_fds_[2] = {-1, -1}; void DebuggerConnectionImpl::HandleEvent(struct epoll_event* event) { if (event->data.fd == DebuggerConnectionHandler::listener_fd_) { if (DebuggerConnectionHandler::IsConnected()) { FATAL("Cannot connect to more than one debugger.\n"); } int fd = ServerSocket::Accept(event->data.fd); if (fd < 0) { FATAL("Accepting new debugger connection failed.\n"); } FDUtils::SetBlocking(fd); DebuggerConnectionHandler::AcceptDbgConnection(fd); // TODO(hausner): add the debugger wire socket fd to the event poll queue // once we poll the debugger connection. } else if (event->data.fd == DebuggerConnectionHandler::debugger_fd_) { printf("unexpected: receiving debugger connection event.\n"); UNIMPLEMENTED(); } else { // Sync message. Not yet implemented. UNIMPLEMENTED(); } } void DebuggerConnectionImpl::Handler(uword args) { static const intptr_t kMaxEvents = 4; struct epoll_event events[kMaxEvents]; while (1) { const int no_timeout = -1; intptr_t result = TEMP_FAILURE_RETRY( epoll_wait(epoll_fd_, events, kMaxEvents, no_timeout)); ASSERT(EAGAIN == EWOULDBLOCK); if (result == -1) { if (errno != EWOULDBLOCK) { perror("epoll_wait failed"); } } else { ASSERT(result <= kMaxEvents); for (int i = 0; i < result; i++) { HandleEvent(&events[i]); } } } } void DebuggerConnectionImpl::SetupPollQueue() { int result = TEMP_FAILURE_RETRY(pipe(wakeup_fds_)); if (result != 0) { FATAL1("Pipe creation failed with error %d\n", result); } FDUtils::SetNonBlocking(wakeup_fds_[0]); static const int kEpollInitialSize = 16; epoll_fd_ = TEMP_FAILURE_RETRY(epoll_create(kEpollInitialSize)); if (epoll_fd_ == -1) { FATAL("Failed creating epoll file descriptor"); } // Register the wakeup _fd with the epoll instance. struct epoll_event event; event.events = EPOLLIN; event.data.fd = wakeup_fds_[0]; int status = TEMP_FAILURE_RETRY(epoll_ctl( epoll_fd_, EPOLL_CTL_ADD, wakeup_fds_[0], &event)); if (status == -1) { FATAL("Failed adding wakeup fd to epoll instance"); } // Register the listener_fd with the epoll instance. event.events = EPOLLIN; event.data.fd = DebuggerConnectionHandler::listener_fd_; status = TEMP_FAILURE_RETRY(epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, DebuggerConnectionHandler::listener_fd_, &event)); if (status == -1) { FATAL("Failed adding listener fd to epoll instance"); } } void DebuggerConnectionImpl::StartHandler(int port_number) { ASSERT(DebuggerConnectionHandler::listener_fd_ != -1); SetupPollQueue(); int result = dart::Thread::Start(&DebuggerConnectionImpl::Handler, 0); if (result != 0) { FATAL1("Failed to start debugger connection handler thread: %d\n", result); } }