assert(result == 0);
if(result == 0) {
+#ifdef O_NONBLOCK
+ fcntl(loop->pipefd[0], F_SETFL, O_NONBLOCK);
+ fcntl(loop->pipefd[1], F_SETFL, O_NONBLOCK);
+#endif
io_add(loop, &loop->signalio, signalio_handler, NULL, loop->pipefd[0], IO_READ);
}
}
loop->idle_data = data;
}
+static void check_bad_fds(event_loop_t *loop) {
+ // Just call all registered callbacks and have them check their fds
+
+ do {
+ loop->deletion = false;
+
+ for splay_each(io_t, io, &loop->ios) {
+ if(io->flags & IO_WRITE) {
+ io->cb(loop, io->data, IO_WRITE);
+ }
+
+ if(loop->deletion) {
+ break;
+ }
+
+ if(io->flags & IO_READ) {
+ io->cb(loop, io->data, IO_READ);
+ }
+
+ if(loop->deletion) {
+ break;
+ }
+ }
+ } while(loop->deletion);
+
+ // Rebuild the fdsets
+
+ memset(&loop->readfds, 0, sizeof(loop->readfds));
+ memset(&loop->writefds, 0, sizeof(loop->writefds));
+
+ for splay_each(io_t, io, &loop->ios) {
+ if(io->flags & IO_READ) {
+ FD_SET(io->fd, &loop->readfds);
+ io->cb(loop, io->data, IO_READ);
+ }
+
+ if(io->flags & IO_WRITE) {
+ FD_SET(io->fd, &loop->writefds);
+ io->cb(loop, io->data, IO_WRITE);
+ }
+
+ }
+}
+
bool event_loop_run(event_loop_t *loop, pthread_mutex_t *mutex) {
assert(mutex);
fd_set readable;
fd_set writable;
+ int errors = 0;
while(loop->running) {
clock_gettime(EVENT_CLOCK, &loop->now);
if(sockwouldblock(errno)) {
continue;
} else {
- return false;
+ errors++;
+
+ if(errors > 10) {
+ return false;
+ }
+
+ check_bad_fds(loop);
+ continue;
}
}
+ errors = 0;
+
if(!n) {
continue;
}
fcntl(nfd, F_SETFD, FD_CLOEXEC);
#endif
+#ifdef O_NONBLOCK
+ int flags = fcntl(nfd, F_GETFL);
+
+ if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) {
+ closesocket(nfd);
+ logger(mesh, MESHLINK_ERROR, "System call `%s' failed: %s", "fcntl", strerror(errno));
+ return -1;
+ }
+
+#elif defined(WIN32)
+ unsigned long arg = 1;
+
+ if(ioctlsocket(nfd, FIONBIO, &arg) != 0) {
+ closesocket(nfd);
+ logger(mesh, MESHLINK_ERROR, "Call to `%s' failed: %s", "ioctlsocket", sockstrerror(sockerrno));
+ return -1;
+ }
+
+#endif
int option = 1;
setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof(option));
for(int i = 0; i < mesh->listen_sockets; i++) {
io_del(&mesh->loop, &mesh->listen_socket[i].tcp);
io_del(&mesh->loop, &mesh->listen_socket[i].udp);
- close(mesh->listen_socket[i].tcp.fd);
- close(mesh->listen_socket[i].udp.fd);
+ closesocket(mesh->listen_socket[i].tcp.fd);
+ closesocket(mesh->listen_socket[i].udp.fd);
}
mesh->listen_sockets = 0;
for(int i = 0; i < mesh->listen_sockets; i++) {
io_del(&mesh->loop, &mesh->listen_socket[i].tcp);
io_del(&mesh->loop, &mesh->listen_socket[i].udp);
- close(mesh->listen_socket[i].tcp.fd);
- close(mesh->listen_socket[i].udp.fd);
+ closesocket(mesh->listen_socket[i].tcp.fd);
+ closesocket(mesh->listen_socket[i].udp.fd);
}
exit_requests(mesh);