Add an always trigger list, so we can handle non-socket IO properly.

This commit is contained in:
Ian Gulliver
2016-02-26 11:12:45 -08:00
parent 680cce544f
commit 8d9a11076b
3 changed files with 35 additions and 6 deletions

View File

@@ -19,6 +19,7 @@ uint32_t peer_count_in = 0, peer_count_out = 0;
static int peer_epoll_fd; static int peer_epoll_fd;
static int peer_shutdown_fd; static int peer_shutdown_fd;
static bool peer_shutdown_flag = false; static bool peer_shutdown_flag = false;
static struct list_head peer_always_trigger_head = LIST_HEAD_INIT(peer_always_trigger_head);
static void peer_shutdown_handler(struct peer *peer) { static void peer_shutdown_handler(struct peer *peer) {
fprintf(stderr, "X %s: Shutting down\n", server_id); fprintf(stderr, "X %s: Shutting down\n", server_id);
@@ -59,11 +60,28 @@ void peer_epoll_add(struct peer *peer, uint32_t events) {
.ptr = peer, .ptr = peer,
}, },
}; };
assert(!epoll_ctl(peer_epoll_fd, EPOLL_CTL_ADD, peer->fd, &ev)); peer->always_trigger = false;
int res = epoll_ctl(peer_epoll_fd, EPOLL_CTL_ADD, peer->fd, &ev);
if (res == -1 && errno == EPERM) {
// Not a socket
if (events) {
list_add(&peer->peer_always_trigger_list, &peer_always_trigger_head);
peer->always_trigger = true;
}
} else {
assert(!res);
}
} }
void peer_epoll_del(struct peer *peer) { void peer_epoll_del(struct peer *peer) {
assert(!epoll_ctl(peer_epoll_fd, EPOLL_CTL_DEL, peer->fd, NULL)); int res = epoll_ctl(peer_epoll_fd, EPOLL_CTL_DEL, peer->fd, NULL);
if (res == -1 && errno == EPERM) {
if (peer->always_trigger) {
list_del(&peer->peer_always_trigger_list);
}
} else {
assert(!res);
}
} }
void peer_call(struct peer *peer) { void peer_call(struct peer *peer) {
@@ -85,7 +103,8 @@ void peer_loop() {
} }
#define MAX_EVENTS 10 #define MAX_EVENTS 10
struct epoll_event events[MAX_EVENTS]; struct epoll_event events[MAX_EVENTS];
int nfds = epoll_wait(peer_epoll_fd, events, MAX_EVENTS, wakeup_get_delay()); int delay = list_is_empty(&peer_always_trigger_head) ? wakeup_get_delay() : 0;
int nfds = epoll_wait(peer_epoll_fd, events, MAX_EVENTS, delay);
if (nfds == -1 && errno == EINTR) { if (nfds == -1 && errno == EINTR) {
continue; continue;
} }
@@ -93,7 +112,14 @@ void peer_loop() {
for (int n = 0; n < nfds; n++) { for (int n = 0; n < nfds; n++) {
struct peer *peer = events[n].data.ptr; struct peer *peer = events[n].data.ptr;
peer->event_handler(peer); peer_call(peer);
}
{
struct peer *iter, *next;
list_for_each_entry_safe(iter, next, &peer_always_trigger_head, peer_always_trigger_list) {
peer_call(iter);
}
} }
wakeup_dispatch(); wakeup_dispatch();

View File

@@ -2,12 +2,16 @@
#include <sys/epoll.h> #include <sys/epoll.h>
#include "list.h"
// All specific peer structs must be castable to this. // All specific peer structs must be castable to this.
struct peer; struct peer;
typedef void (*peer_event_handler)(struct peer *); typedef void (*peer_event_handler)(struct peer *);
struct peer { struct peer {
int fd; int fd;
peer_event_handler event_handler; peer_event_handler event_handler;
struct list_head peer_always_trigger_list;
bool always_trigger;
}; };
extern uint32_t peer_count_in, peer_count_out; extern uint32_t peer_count_in, peer_count_out;

View File

@@ -98,9 +98,8 @@ void send_init() {
void send_cleanup() { void send_cleanup() {
for (size_t i = 0; i < NUM_SERIALIZERS; i++) { for (size_t i = 0; i < NUM_SERIALIZERS; i++) {
struct serializer *serializer = &serializers[i];
struct send *iter, *next; struct send *iter, *next;
list_for_each_entry_safe(iter, next, &serializer->send_head, send_list) { list_for_each_entry_safe(iter, next, &serializers[i].send_head, send_list) {
send_del(iter); send_del(iter);
} }
} }