87a43bef60
This is a slightly cleaned up version of the code that Devon created. All of eventhandler and socket in bin is designed for async communication only. Therefore, it does not make much sense to use it for something as simple as this. I have put the sync send and receive operations into DebuggerConnectionImpl instead of attempting to use the async Socket::Read and Socket::Write. R=devoncarew@google.com,sgjesse@google.com,hausner@google.com BUG= Review URL: https://codereview.chromium.org//11642019 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@16336 260f80e4-7a28-3924-810f-c04153c831b5
118 lines
3.6 KiB
C++
118 lines
3.6 KiB
C++
// 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 <errno.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/epoll.h>
|
|
|
|
#include "bin/dbg_connection.h"
|
|
#include "bin/fdutils.h"
|
|
#include "bin/log.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 == wakeup_fds_[0]) {
|
|
// Sync message. Not yet implemented.
|
|
UNIMPLEMENTED();
|
|
} else {
|
|
Log::Print("unexpected: receiving debugger connection event.\n");
|
|
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);
|
|
}
|
|
}
|
|
|
|
|
|
intptr_t DebuggerConnectionImpl::Send(intptr_t socket,
|
|
const char* buf,
|
|
int len) {
|
|
return TEMP_FAILURE_RETRY(write(socket, buf, len));
|
|
}
|
|
|
|
|
|
intptr_t DebuggerConnectionImpl::Receive(intptr_t socket, char* buf, int len) {
|
|
return TEMP_FAILURE_RETRY(read(socket, buf, len));
|
|
}
|