6#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)
18#include <sys/timerfd.h>
48static void RemoveFromEpollInstance(intptr_t epoll_fd_, DescriptorInfo* di) {
50 epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, di->fd(),
nullptr));
53static void AddToEpollInstance(intptr_t epoll_fd_, DescriptorInfo* di) {
54 struct epoll_event
event;
55 event.events = EPOLLRDHUP | di->GetPollEvents();
56 if (!di->IsListeningSocket()) {
57 event.events |= EPOLLET;
74 : socket_map_(&SimpleHashMap::SamePointerValue, 16) {
78 FATAL(
"Pipe creation failed");
80 if (!FDUtils::SetNonBlocking(interrupt_fds_[0])) {
81 FATAL(
"Failed to set pipe fd non blocking\n");
83 if (!FDUtils::SetCloseOnExec(interrupt_fds_[0])) {
84 FATAL(
"Failed to set pipe fd close on exec\n");
86 if (!FDUtils::SetCloseOnExec(interrupt_fds_[1])) {
87 FATAL(
"Failed to set pipe fd close on exec\n");
92 const int kEpollInitialSize = 64;
94 if (epoll_fd_ == -1) {
95 FATAL(
"Failed creating epoll file descriptor: %i", errno);
97 if (!FDUtils::SetCloseOnExec(epoll_fd_)) {
98 FATAL(
"Failed to set epoll fd close on exec\n");
101 struct epoll_event
event;
102 event.events = EPOLLIN;
103 event.data.ptr =
nullptr;
105 epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, interrupt_fds_[0], &
event));
107 FATAL(
"Failed adding interrupt fd to epoll instance");
110 if (timer_fd_ == -1) {
111 FATAL(
"Failed creating timerfd file descriptor: %i", errno);
114 event.events = EPOLLIN;
115 event.data.fd = timer_fd_;
119 FATAL(
"Failed adding timerfd fd(%i) to epoll instance: %i", timer_fd_,
124static void DeleteDescriptorInfo(
void*
info) {
125 DescriptorInfo* di =
reinterpret_cast<DescriptorInfo*
>(
info);
130EventHandlerImplementation::~EventHandlerImplementation() {
131 socket_map_.Clear(DeleteDescriptorInfo);
134 close(interrupt_fds_[0]);
135 close(interrupt_fds_[1]);
138void EventHandlerImplementation::UpdateEpollInstance(intptr_t old_mask,
139 DescriptorInfo* di) {
140 intptr_t new_mask = di->Mask();
141 if ((old_mask != 0) && (new_mask == 0)) {
142 RemoveFromEpollInstance(epoll_fd_, di);
143 }
else if ((old_mask == 0) && (new_mask != 0)) {
144 AddToEpollInstance(epoll_fd_, di);
145 }
else if ((old_mask != 0) && (new_mask != 0) && (old_mask != new_mask)) {
146 ASSERT(!di->IsListeningSocket());
147 RemoveFromEpollInstance(epoll_fd_, di);
148 AddToEpollInstance(epoll_fd_, di);
152DescriptorInfo* EventHandlerImplementation::GetDescriptorInfo(
157 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd),
true);
159 DescriptorInfo* di =
reinterpret_cast<DescriptorInfo*
>(entry->value);
164 di =
new DescriptorInfoMultiple(fd);
166 di =
new DescriptorInfoSingle(fd);
174void EventHandlerImplementation::WakeupHandler(intptr_t
id,
177 InterruptMessage msg;
179 msg.dart_port = dart_port;
189 FATAL(
"Interrupt message failure: %s", strerror(errno));
191 FATAL(
"Interrupt message failure: expected to write %" Pd
192 " bytes, but wrote %" Pd ".",
198void EventHandlerImplementation::HandleInterruptFd() {
200 InterruptMessage msg[MAX_MESSAGES];
205 timeout_queue_.UpdateTimeout(msg[
i].dart_port, msg[
i].
data);
211 Socket* socket =
reinterpret_cast<Socket*
>(msg[
i].id);
212 RefCntReleaseScope<Socket> rs(socket);
213 if (socket->fd() == -1) {
219 ASSERT(!di->IsListeningSocket());
223 ASSERT(!di->IsListeningSocket());
230 Process::ClearSignalHandlerByFd(di->fd(), socket->isolate_port());
232 intptr_t old_mask = di->Mask();
235 di->RemovePort(
port);
237 intptr_t new_mask = di->Mask();
238 UpdateEpollInstance(old_mask, di);
240 intptr_t fd = di->fd();
241 ASSERT(fd == socket->fd());
242 if (di->IsListeningSocket()) {
246 ListeningSocketRegistry* registry =
247 ListeningSocketRegistry::Instance();
249 MutexLocker locker(registry->mutex());
251 if (registry->CloseSafe(socket)) {
253 socket_map_.Remove(GetHashmapKeyFromFd(fd),
254 GetHashmapHashFromFd(fd));
261 socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd));
269 intptr_t old_mask = di->Mask();
270 di->ReturnTokens(msg[
i].dart_port,
count);
271 UpdateEpollInstance(old_mask, di);
277 intptr_t old_mask = di->Mask();
279 UpdateEpollInstance(old_mask, di);
287void EventHandlerImplementation::UpdateTimerFd() {
288 struct itimerspec it;
289 memset(&it, 0,
sizeof(it));
290 if (timeout_queue_.HasTimeout()) {
291 int64_t millis = timeout_queue_.CurrentTimeout();
292 it.it_value.tv_sec = millis / 1000;
293 it.it_value.tv_nsec = (millis % 1000) * 1000000;
300static void PrintEventMask(intptr_t fd, intptr_t events) {
301 Syslog::Print(
"%d ", fd);
302 if ((events & EPOLLIN) != 0) {
303 Syslog::Print(
"EPOLLIN ");
305 if ((events & EPOLLPRI) != 0) {
306 Syslog::Print(
"EPOLLPRI ");
308 if ((events & EPOLLOUT) != 0) {
309 Syslog::Print(
"EPOLLOUT ");
311 if ((events & EPOLLERR) != 0) {
312 Syslog::Print(
"EPOLLERR ");
314 if ((events & EPOLLHUP) != 0) {
315 Syslog::Print(
"EPOLLHUP ");
317 if ((events & EPOLLRDHUP) != 0) {
318 Syslog::Print(
"EPOLLRDHUP ");
321 EPOLLIN | EPOLLPRI | EPOLLOUT | EPOLLERR | EPOLLHUP | EPOLLRDHUP;
322 if ((events & ~all_events) != 0) {
323 Syslog::Print(
"(and %08x) ", events & ~all_events);
325 Syslog::Print(
"(available %d) ", FDUtils::AvailableBytes(fd));
331intptr_t EventHandlerImplementation::GetPollEvents(intptr_t events,
332 DescriptorInfo* di) {
334 PrintEventMask(di->fd(), events);
336 if ((events & EPOLLERR) != 0) {
338 return ((events & EPOLLIN) != 0) ? (1 <<
kErrorEvent) : 0;
340 intptr_t event_mask = 0;
341 if ((events & EPOLLIN) != 0) {
344 if ((events & EPOLLOUT) != 0) {
347 if ((events & (EPOLLHUP | EPOLLRDHUP)) != 0) {
353void EventHandlerImplementation::HandleEvents(
struct epoll_event* events,
355 bool interrupt_seen =
false;
356 for (
int i = 0;
i <
size;
i++) {
357 if (events[
i].
data.ptr ==
nullptr) {
358 interrupt_seen =
true;
359 }
else if (events[
i].
data.fd == timer_fd_) {
362 read(timer_fd_, &val,
sizeof(val)));
363 if (timeout_queue_.HasTimeout()) {
364 DartUtils::PostNull(timeout_queue_.CurrentPort());
365 timeout_queue_.RemoveCurrent();
370 reinterpret_cast<DescriptorInfo*
>(events[
i].data.ptr);
371 const intptr_t old_mask = di->Mask();
372 const intptr_t event_mask = GetPollEvents(events[
i].events, di);
374 di->NotifyAllDartPorts(event_mask);
375 UpdateEpollInstance(old_mask, di);
376 }
else if (event_mask != 0) {
379 UpdateEpollInstance(old_mask, di);
380 DartUtils::PostInt32(
port, event_mask);
384 if (interrupt_seen) {
391void EventHandlerImplementation::Poll(
uword args) {
392 ThreadSignalBlocker signal_blocker(SIGPROF);
393 const intptr_t kMaxEvents = 16;
394 struct epoll_event events[kMaxEvents];
395 EventHandler* handler =
reinterpret_cast<EventHandler*
>(
args);
396 EventHandlerImplementation* handler_impl = &handler->delegate_;
397 ASSERT(handler_impl !=
nullptr);
399 while (!handler_impl->shutdown_) {
401 epoll_wait(handler_impl->epoll_fd_, events, kMaxEvents, -1));
402 ASSERT(EAGAIN == EWOULDBLOCK);
404 if (errno != EWOULDBLOCK) {
405 perror(
"Poll failed");
408 handler_impl->HandleEvents(events,
result);
411 DEBUG_ASSERT(ReferenceCounted<Socket>::instances() == 0);
412 handler->NotifyShutdownDone();
415void EventHandlerImplementation::Start(EventHandler* handler) {
417 Thread::Start(
"dart:io EventHandler", &EventHandlerImplementation::Poll,
418 reinterpret_cast<uword>(handler));
420 FATAL(
"Failed to start event handler thread %d",
result);
431 WakeupHandler(
id, dart_port,
data);
434void* EventHandlerImplementation::GetHashmapKeyFromFd(intptr_t fd) {
436 return reinterpret_cast<void*
>(fd + 1);
439uint32_t EventHandlerImplementation::GetHashmapHashFromFd(intptr_t fd) {
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
static bool read(SkStream *stream, void *buffer, size_t amount)
#define DEBUG_ASSERT(cond)
static uint32_t WordHash(intptr_t key)
virtual intptr_t Mask()=0
EventHandlerImplementation()
#define IS_COMMAND(data, command_bit)
#define IS_LISTENING_SOCKET(data)
#define IS_SIGNAL_SOCKET(data)
#define TOKEN_COUNT(data)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
int SendData(MHD_Connection *connection, const SkData *data, const char *type, bool setContentDisposition, const char *dispositionString)
static constexpr intptr_t kTimerId
static constexpr intptr_t kShutdownId
static constexpr intptr_t kInterruptMessageSize
static void Shutdown(Dart_NativeArguments args)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service port
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
#define TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER(expression)
#define NO_RETRY_EXPECTED(expression)
#define VOID_TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER(expression)
#define VOID_NO_RETRY_EXPECTED(expression)
std::shared_ptr< const fml::Mapping > data
int timerfd_settime(int ufc, int flags, const struct itimerspec *utmr, struct itimerspec *otmr)
int timerfd_create(int clockid, int flags)
#define TFD_TIMER_ABSTIME