3a7485dfa0
Platform-dependent code of the Linux version of the debugger wire protocol. Review URL: https://chromiumcodereview.appspot.com//10572028 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8913 260f80e4-7a28-3924-810f-c04153c831b5
105 lines
3.3 KiB
C++
105 lines
3.3 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/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);
|
|
}
|
|
}
|