ebbc2020a2
Review URL: https://codereview.chromium.org//14341015 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@22032 260f80e4-7a28-3924-810f-c04153c831b5
130 lines
3.8 KiB
C++
130 lines
3.8 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 "platform/globals.h"
|
|
#if defined(TARGET_OS_LINUX)
|
|
|
|
#include <errno.h> // NOLINT
|
|
#include <stdio.h> // NOLINT
|
|
#include <stdlib.h> // NOLINT
|
|
#include <sys/epoll.h> // NOLINT
|
|
|
|
#include "bin/dbg_connection.h"
|
|
#include "bin/fdutils.h"
|
|
#include "bin/log.h"
|
|
#include "bin/socket.h"
|
|
|
|
|
|
namespace dart {
|
|
namespace bin {
|
|
|
|
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));
|
|
}
|
|
|
|
} // namespace bin
|
|
} // namespace dart
|
|
|
|
#endif // defined(TARGET_OS_LINUX)
|