diff --git a/skynet-src/socket_epoll.h b/skynet-src/socket_epoll.h index 2fc8903a..62b1614a 100644 --- a/skynet-src/socket_epoll.h +++ b/skynet-src/socket_epoll.h @@ -59,6 +59,7 @@ sp_wait(int efd, struct event *e, int max) { unsigned flag = ev[i].events; e[i].write = (flag & EPOLLOUT) != 0; e[i].read = (flag & EPOLLIN) != 0; + e[i].error = (flag & EPOLLERR) != 0; } return n; diff --git a/skynet-src/socket_kqueue.h b/skynet-src/socket_kqueue.h index 54884b6a..8aa31203 100644 --- a/skynet-src/socket_kqueue.h +++ b/skynet-src/socket_kqueue.h @@ -38,17 +38,17 @@ static int sp_add(int kfd, int sock, void *ud) { struct kevent ke; EV_SET(&ke, sock, EVFILT_READ, EV_ADD, 0, 0, ud); - if (kevent(kfd, &ke, 1, NULL, 0, NULL) == -1) { + if (kevent(kfd, &ke, 1, NULL, 0, NULL) == -1 || ke.flags & EV_ERROR) { return 1; } EV_SET(&ke, sock, EVFILT_WRITE, EV_ADD, 0, 0, ud); - if (kevent(kfd, &ke, 1, NULL, 0, NULL) == -1) { + if (kevent(kfd, &ke, 1, NULL, 0, NULL) == -1 || ke.flags & EV_ERROR) { EV_SET(&ke, sock, EVFILT_READ, EV_DELETE, 0, 0, NULL); kevent(kfd, &ke, 1, NULL, 0, NULL); return 1; } EV_SET(&ke, sock, EVFILT_WRITE, EV_DISABLE, 0, 0, ud); - if (kevent(kfd, &ke, 1, NULL, 0, NULL) == -1) { + if (kevent(kfd, &ke, 1, NULL, 0, NULL) == -1 || ke.flags & EV_ERROR) { sp_del(kfd, sock); return 1; } @@ -59,7 +59,7 @@ static void sp_write(int kfd, int sock, void *ud, bool enable) { struct kevent ke; EV_SET(&ke, sock, EVFILT_WRITE, enable ? EV_ENABLE : EV_DISABLE, 0, 0, ud); - if (kevent(kfd, &ke, 1, NULL, 0, NULL) == -1) { + if (kevent(kfd, &ke, 1, NULL, 0, NULL) == -1 || ke.flags & EV_ERROR) { // todo: check error } } @@ -75,6 +75,7 @@ sp_wait(int kfd, struct event *e, int max) { unsigned filter = ev[i].filter; e[i].write = (filter == EVFILT_WRITE); e[i].read = (filter == EVFILT_READ); + e[i].error = false; // kevent has not error event } return n; diff --git a/skynet-src/socket_poll.h b/skynet-src/socket_poll.h index 0f36308a..cfd7e870 100644 --- a/skynet-src/socket_poll.h +++ b/skynet-src/socket_poll.h @@ -9,6 +9,7 @@ struct event { void * s; bool read; bool write; + bool error; }; static bool sp_invalid(poll_fd fd); diff --git a/skynet-src/socket_server.c b/skynet-src/socket_server.c index 4f381280..3841f233 100644 --- a/skynet-src/socket_server.c +++ b/skynet-src/socket_server.c @@ -1302,6 +1302,21 @@ socket_server_poll(struct socket_server *ss, struct socket_message * result, int break; return type; } + if (e->error) { + // close when error + int error; + socklen_t len = sizeof(error); + int code = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &error, &len); + if (code < 0) { + result->data = strerror(errno); + } else if (error != 0) { + result->data = strerror(error); + } else { + result->data = "Unknown error"; + } + force_close(ss, s, result); + return SOCKET_ERR; + } break; } }