OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 #include "platform/globals.h" | |
6 #if defined(TARGET_OS_LINUX) | |
7 | |
8 #include <errno.h> // NOLINT | |
9 #include <stdio.h> // NOLINT | |
10 #include <stdlib.h> // NOLINT | |
11 #include <sys/epoll.h> // NOLINT | |
12 | |
13 #include "platform/signal_blocker.h" | |
14 #include "bin/dbg_connection.h" | |
15 #include "bin/fdutils.h" | |
16 #include "bin/log.h" | |
17 #include "bin/socket.h" | |
18 | |
19 | |
20 namespace dart { | |
21 namespace bin { | |
22 | |
23 int DebuggerConnectionImpl::epoll_fd_ = -1; | |
24 int DebuggerConnectionImpl::wakeup_fds_[2] = {-1, -1}; | |
25 | |
26 | |
27 void DebuggerConnectionImpl::HandleEvent(struct epoll_event* event) { | |
28 if (event->data.fd == DebuggerConnectionHandler::listener_fd_) { | |
29 if (DebuggerConnectionHandler::IsConnected()) { | |
30 FATAL("Cannot connect to more than one debugger.\n"); | |
31 } | |
32 intptr_t fd = ServerSocket::Accept(event->data.fd); | |
33 if (fd < 0) { | |
34 FATAL("Accepting new debugger connection failed.\n"); | |
35 } | |
36 FDUtils::SetBlocking(fd); | |
37 DebuggerConnectionHandler::AcceptDbgConnection(fd); | |
38 // TODO(hausner): add the debugger wire socket fd to the event poll queue | |
39 // once we poll the debugger connection. | |
40 } else if (event->data.fd == wakeup_fds_[0]) { | |
41 // Sync message. Not yet implemented. | |
42 UNIMPLEMENTED(); | |
43 } else { | |
44 Log::Print("unexpected: receiving debugger connection event.\n"); | |
45 UNIMPLEMENTED(); | |
46 } | |
47 } | |
48 | |
49 | |
50 void DebuggerConnectionImpl::Handler(uword args) { | |
51 static const int kMaxEvents = 4; | |
52 struct epoll_event events[kMaxEvents]; | |
53 while (1) { | |
54 const int no_timeout = -1; | |
55 intptr_t result = TEMP_FAILURE_RETRY( | |
56 epoll_wait(epoll_fd_, events, kMaxEvents, no_timeout)); | |
57 ASSERT(EAGAIN == EWOULDBLOCK); | |
58 if (result == -1) { | |
59 if (errno != EWOULDBLOCK) { | |
60 perror("epoll_wait failed"); | |
61 } | |
62 } else { | |
63 ASSERT(result <= kMaxEvents); | |
64 for (int i = 0; i < result; i++) { | |
65 HandleEvent(&events[i]); | |
66 } | |
67 } | |
68 } | |
69 } | |
70 | |
71 | |
72 void DebuggerConnectionImpl::SetupPollQueue() { | |
73 int result = NO_RETRY_EXPECTED(pipe(wakeup_fds_)); | |
74 if (result != 0) { | |
75 FATAL1("Pipe creation failed with error %d\n", result); | |
76 } | |
77 FDUtils::SetNonBlocking(wakeup_fds_[0]); | |
78 | |
79 static const int kEpollInitialSize = 16; | |
80 epoll_fd_ = NO_RETRY_EXPECTED(epoll_create(kEpollInitialSize)); | |
81 if (epoll_fd_ == -1) { | |
82 FATAL("Failed creating epoll file descriptor"); | |
83 } | |
84 | |
85 // Register the wakeup _fd with the epoll instance. | |
86 struct epoll_event event; | |
87 event.events = EPOLLIN; | |
88 event.data.fd = wakeup_fds_[0]; | |
89 int status = NO_RETRY_EXPECTED(epoll_ctl( | |
90 epoll_fd_, EPOLL_CTL_ADD, wakeup_fds_[0], &event)); | |
91 if (status == -1) { | |
92 FATAL("Failed adding wakeup fd to epoll instance"); | |
93 } | |
94 | |
95 // Register the listener_fd with the epoll instance. | |
96 event.events = EPOLLIN; | |
97 event.data.fd = DebuggerConnectionHandler::listener_fd_; | |
98 status = NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, | |
99 DebuggerConnectionHandler::listener_fd_, &event)); | |
100 if (status == -1) { | |
101 FATAL("Failed adding listener fd to epoll instance"); | |
102 } | |
103 } | |
104 | |
105 | |
106 void DebuggerConnectionImpl::StartHandler(int port_number) { | |
107 ASSERT(DebuggerConnectionHandler::listener_fd_ != -1); | |
108 SetupPollQueue(); | |
109 int result = Thread::Start(&DebuggerConnectionImpl::Handler, 0); | |
110 if (result != 0) { | |
111 FATAL1("Failed to start debugger connection handler thread: %d\n", result); | |
112 } | |
113 } | |
114 | |
115 | |
116 intptr_t DebuggerConnectionImpl::Send(intptr_t socket, | |
117 const char* buf, | |
118 int len) { | |
119 return TEMP_FAILURE_RETRY(write(socket, buf, len)); | |
120 } | |
121 | |
122 | |
123 intptr_t DebuggerConnectionImpl::Receive(intptr_t socket, char* buf, int len) { | |
124 return TEMP_FAILURE_RETRY(read(socket, buf, len)); | |
125 } | |
126 | |
127 } // namespace bin | |
128 } // namespace dart | |
129 | |
130 #endif // defined(TARGET_OS_LINUX) | |
OLD | NEW |