Add an always trigger list, so we can handle non-socket IO properly.
This commit is contained in:
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user