Created
December 9, 2017 19:32
-
-
Save alfredh/898d565106731d6525616a9a6f6c78b8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 49834b7afd0fe31660108271ef7657a34caa6a6d Mon Sep 17 00:00:00 2001 | |
From: "Alfred E. Heggestad" <[email protected]> | |
Date: Sat, 7 Oct 2017 15:49:44 +0200 | |
Subject: [PATCH] main: keep fd handlers in list | |
Experimental code in order to try to solve | |
sockets for Windows. On windows the "int fd" is actually | |
of type "SOCKET fd" and the range goes from 0 to very large. | |
ref #61 | |
--- | |
mk/re.mk | 2 +- | |
src/main/main.c | 179 ++++++++++++++++++++++++++++++++++++++------------------ | |
2 files changed, 122 insertions(+), 59 deletions(-) | |
diff --git a/mk/re.mk b/mk/re.mk | |
index 944da62..91bfea5 100644 | |
--- a/mk/re.mk | |
+++ b/mk/re.mk | |
@@ -599,7 +599,7 @@ ifneq ($(HAVE_EPOLL),) | |
CFLAGS += -DHAVE_EPOLL | |
endif | |
ifneq ($(HAVE_KQUEUE),) | |
-CFLAGS += -DHAVE_KQUEUE | |
+#CFLAGS += -DHAVE_KQUEUE # NOTE: Broken in this branch | |
endif | |
CFLAGS += -DHAVE_UNAME | |
CFLAGS += -DHAVE_UNISTD_H | |
diff --git a/src/main/main.c b/src/main/main.c | |
index 762b0b4..070784d 100644 | |
--- a/src/main/main.c | |
+++ b/src/main/main.c | |
@@ -84,16 +84,19 @@ enum { | |
}; | |
+struct fdh { | |
+ struct le le; /**< Linked-list element */ | |
+ int fd; /**< File Descriptor */ | |
+ int flags; /**< Polling flags (Read, Write, etc.) */ | |
+ fd_h *fh; /**< Event handler */ | |
+ void *arg; /**< Handler argument */ | |
+}; | |
+ | |
+ | |
/** Polling loop data */ | |
struct re { | |
- /** File descriptor handler set */ | |
- struct { | |
- int flags; /**< Polling flags (Read, Write, etc.) */ | |
- fd_h *fh; /**< Event handler */ | |
- void *arg; /**< Handler argument */ | |
- } *fhs; | |
+ struct list fdhl; /**< List of File descriptor handlers */ | |
int maxfds; /**< Maximum number of polling fds */ | |
- int nfds; /**< Number of active file descriptors */ | |
enum poll_method method; /**< The current polling method */ | |
bool update; /**< File descriptor set need updating */ | |
bool polling; /**< Is polling flag */ | |
@@ -121,8 +124,7 @@ struct re { | |
}; | |
static struct re global_re = { | |
- NULL, | |
- 0, | |
+ LIST_INIT, | |
0, | |
METHOD_NULL, | |
false, | |
@@ -230,21 +232,21 @@ static struct re *re_get(void) | |
* @param fd File descriptor | |
* @param flags Event flags | |
*/ | |
-static void fd_handler(struct re *re, int fd, int flags) | |
+static void fd_handler(struct fdh *fdh, int flags) | |
{ | |
const uint64_t tick = tmr_jiffies(); | |
uint32_t diff; | |
DEBUG_INFO("event on fd=%d (flags=0x%02x)...\n", fd, flags); | |
- re->fhs[fd].fh(flags, re->fhs[fd].arg); | |
+ fdh->fh(flags, fdh->arg); | |
diff = (uint32_t)(tmr_jiffies() - tick); | |
if (diff > MAX_BLOCKING) { | |
DEBUG_WARNING("long async blocking: %u>%u ms (h=%p arg=%p)\n", | |
diff, MAX_BLOCKING, | |
- re->fhs[fd].fh, re->fhs[fd].arg); | |
+ fdh->fh, fdh->arg); | |
} | |
} | |
#endif | |
@@ -373,6 +375,7 @@ static int set_kqueue_fds(struct re *re, int fd, int flags) | |
#endif | |
+#if 0 | |
/** | |
* Rebuild the file descriptor mapping table. This must be done whenever | |
* the polling method is changed. | |
@@ -417,6 +420,7 @@ static int rebuild_fds(struct re *re) | |
return err; | |
} | |
+#endif | |
static int poll_init(struct re *re) | |
@@ -496,7 +500,6 @@ static void poll_close(struct re *re) | |
{ | |
DEBUG_INFO("poll close\n"); | |
- re->fhs = mem_deref(re->fhs); | |
re->maxfds = 0; | |
#ifdef HAVE_POLL | |
@@ -551,6 +554,30 @@ static int poll_setup(struct re *re) | |
} | |
+static void fdh_destructor(void *data) | |
+{ | |
+ struct fdh *fdh = data; | |
+ | |
+ list_unlink(&fdh->le); | |
+} | |
+ | |
+ | |
+static struct fdh *fdh_lookup(const struct re *re, int fd) | |
+{ | |
+ struct le *le; | |
+ | |
+ for (le = re->fdhl.head; le; le = le->next) { | |
+ | |
+ struct fdh *fdh = le->data; | |
+ | |
+ if (fdh->fd == fd) | |
+ return fdh; | |
+ } | |
+ | |
+ return NULL; | |
+} | |
+ | |
+ | |
/** | |
* Listen for events on a file descriptor | |
* | |
@@ -579,23 +606,30 @@ int fd_listen(int fd, int flags, fd_h *fh, void *arg) | |
return err; | |
} | |
- if (fd >= re->maxfds) { | |
- if (flags) { | |
- DEBUG_WARNING("fd_listen: fd=%d flags=0x%02x" | |
- " - Max %d fds\n", | |
- fd, flags, re->maxfds); | |
- } | |
- return EMFILE; | |
+ struct fdh *fdh; | |
+ | |
+ fdh = fdh_lookup(re, fd); | |
+ if (fdh) { | |
+ | |
+ /* Update fh set */ | |
+ fdh->fd = fd; | |
+ fdh->flags = flags; | |
+ fdh->fh = fh; | |
+ fdh->arg = arg; | |
} | |
+ else { | |
+ fdh = mem_zalloc(sizeof(*fdh), fdh_destructor); | |
+ | |
+ /* Add fh set */ | |
+ fdh->fd = fd; | |
+ fdh->flags = flags; | |
+ fdh->fh = fh; | |
+ fdh->arg = arg; | |
- /* Update fh set */ | |
- if (re->fhs) { | |
- re->fhs[fd].flags = flags; | |
- re->fhs[fd].fh = fh; | |
- re->fhs[fd].arg = arg; | |
+ list_append(&re->fdhl, &fdh->le, fdh); | |
} | |
- re->nfds = max(re->nfds, fd+1); | |
+ re->update = true; | |
switch (re->method) { | |
@@ -642,7 +676,18 @@ int fd_listen(int fd, int flags, fd_h *fh, void *arg) | |
*/ | |
void fd_close(int fd) | |
{ | |
- (void)fd_listen(fd, 0, NULL, NULL); | |
+ struct re *re = re_get(); | |
+ | |
+ struct fdh *fdh = fdh_lookup(re, fd); | |
+ if (fdh) { | |
+ mem_deref(fdh); | |
+ | |
+ re->update = true; | |
+ } | |
+ else { | |
+ DEBUG_NOTICE("fd_close: fd=%d not found\n", fd); | |
+ } | |
+ | |
} | |
@@ -656,10 +701,11 @@ void fd_close(int fd) | |
static int fd_poll(struct re *re) | |
{ | |
const uint64_t to = tmr_next_timeout(&re->tmrl); | |
- int i, n; | |
+ int n; | |
#ifdef HAVE_SELECT | |
fd_set rfds, wfds, efds; | |
#endif | |
+ struct le *le; | |
DEBUG_INFO("next timer: %llu ms\n", to); | |
@@ -676,22 +722,29 @@ static int fd_poll(struct re *re) | |
#ifdef HAVE_SELECT | |
case METHOD_SELECT: { | |
struct timeval tv; | |
+ int nfds = 0; | |
/* Clear and update fd sets */ | |
FD_ZERO(&rfds); | |
FD_ZERO(&wfds); | |
FD_ZERO(&efds); | |
- for (i=0; i<re->nfds; i++) { | |
- if (!re->fhs[i].fh) | |
+ /* loop through list of file-descriptor handlers */ | |
+ for (le = re->fdhl.head; le; le = le->next) { | |
+ | |
+ struct fdh *fdh = le->data; | |
+ | |
+ if (!fdh->fh) | |
continue; | |
- if (re->fhs[i].flags & FD_READ) | |
- FD_SET(i, &rfds); | |
- if (re->fhs[i].flags & FD_WRITE) | |
- FD_SET(i, &wfds); | |
- if (re->fhs[i].flags & FD_EXCEPT) | |
- FD_SET(i, &efds); | |
+ if (fdh->flags & FD_READ) | |
+ FD_SET(fdh->fd, &rfds); | |
+ if (fdh->flags & FD_WRITE) | |
+ FD_SET(fdh->fd, &wfds); | |
+ if (fdh->flags & FD_EXCEPT) | |
+ FD_SET(fdh->fd, &efds); | |
+ | |
+ nfds = max(nfds, fdh->fd+1); | |
} | |
#ifdef WIN32 | |
@@ -701,7 +754,7 @@ static int fd_poll(struct re *re) | |
#endif | |
tv.tv_usec = (uint32_t) (to % 1000) * 1000; | |
re_unlock(re); | |
- n = select(re->nfds, &rfds, &wfds, &efds, to ? &tv : NULL); | |
+ n = select(nfds, &rfds, &wfds, &efds, to ? &tv : NULL); | |
re_lock(re); | |
} | |
break; | |
@@ -740,9 +793,17 @@ static int fd_poll(struct re *re) | |
return errno; | |
/* Check for events */ | |
- for (i=0; (n > 0) && (i < re->nfds); i++) { | |
+ | |
+ le = re->fdhl.head; | |
+ | |
+ /* NOTE: callback handler might alter the list */ | |
+ while (le) { | |
+ | |
+ struct fdh *fdh = le->data; | |
int fd, flags = 0; | |
+ le = le->next; | |
+ | |
switch (re->method) { | |
#ifdef HAVE_POLL | |
@@ -767,7 +828,8 @@ static int fd_poll(struct re *re) | |
#endif | |
#ifdef HAVE_SELECT | |
case METHOD_SELECT: | |
- fd = i; | |
+ fd = fdh->fd; | |
+ | |
if (FD_ISSET(fd, &rfds)) | |
flags |= FD_READ; | |
if (FD_ISSET(fd, &wfds)) | |
@@ -838,16 +900,18 @@ static int fd_poll(struct re *re) | |
if (!flags) | |
continue; | |
- if (re->fhs[fd].fh) { | |
+ | |
+ if (fdh->fh) { | |
#if MAIN_DEBUG | |
- fd_handler(re, fd, flags); | |
+ fd_handler(fdh, flags); | |
#else | |
- re->fhs[fd].fh(flags, re->fhs[fd].arg); | |
+ fdh->fh(flags, fdh->arg); | |
#endif | |
} | |
/* Check if polling method was changed */ | |
if (re->update) { | |
+ re_printf("- fd_set updated\n"); | |
re->update = false; | |
return 0; | |
} | |
@@ -879,15 +943,6 @@ int fd_setsize(int maxfds) | |
if (!re->maxfds) | |
re->maxfds = maxfds; | |
- if (!re->fhs) { | |
- DEBUG_INFO("fd_setsize: maxfds=%d, allocating %u bytes\n", | |
- re->maxfds, re->maxfds * sizeof(*re->fhs)); | |
- | |
- re->fhs = mem_zalloc(re->maxfds * sizeof(*re->fhs), NULL); | |
- if (!re->fhs) | |
- return ENOMEM; | |
- } | |
- | |
return 0; | |
} | |
@@ -898,20 +953,22 @@ int fd_setsize(int maxfds) | |
void fd_debug(void) | |
{ | |
const struct re *re = re_get(); | |
- int i; | |
+ struct le *le; | |
- if (!re->fhs) | |
+ if (!re) | |
return; | |
- for (i=0; i<re->nfds; i++) { | |
+ for (le = re->fdhl.head; le; le = le->next) { | |
+ | |
+ struct fdh *fdh = le->data; | |
- if (!re->fhs[i].flags) | |
+ if (!fdh->flags) | |
continue; | |
(void)re_fprintf(stderr, | |
"fd %d in use: flags=%x fh=%p arg=%p\n", | |
- i, re->fhs[i].flags, re->fhs[i].fh, | |
- re->fhs[i].arg); | |
+ fdh->fd, fdh->flags, fdh->fh, | |
+ fdh->arg); | |
} | |
} | |
@@ -939,6 +996,8 @@ int re_main(re_signal_h *signalh) | |
struct re *re = re_get(); | |
int err; | |
+ re_printf("$$$ NOTE - USING EXPERIMENTAL RE_MAIN $$$\n"); | |
+ | |
#ifdef HAVE_SIGNAL | |
if (signalh) { | |
(void)signal(SIGINT, signal_handler); | |
@@ -1029,7 +1088,7 @@ int re_debug(struct re_printf *pf, void *unused) | |
err |= re_hprintf(pf, "re main loop:\n"); | |
err |= re_hprintf(pf, " maxfds: %d\n", re->maxfds); | |
- err |= re_hprintf(pf, " nfds: %d\n", re->nfds); | |
+ err |= re_hprintf(pf, " nfds: %d\n", list_count(&re->fdhl)); | |
err |= re_hprintf(pf, " method: %d (%s)\n", re->method, | |
poll_method_name(re->method)); | |
@@ -1094,7 +1153,11 @@ int poll_method_set(enum poll_method method) | |
if (err) | |
return err; | |
+#if 0 | |
return rebuild_fds(re); | |
+#endif | |
+ | |
+ return 0; | |
} | |
-- | |
2.15.1 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment