Skip to content

Commit

Permalink
main: fix windows file descriptors #20
Browse files Browse the repository at this point in the history
  • Loading branch information
johnjuuljensen authored and sreimers committed Sep 29, 2020
1 parent b913aa6 commit d3d38a4
Showing 1 changed file with 66 additions and 28 deletions.
94 changes: 66 additions & 28 deletions src/main/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,17 @@ enum {
#endif
};

/** File descriptor handler struct */
struct fhs {
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 fhs *fhs; /** File descriptor handler set */
int maxfds; /**< Maximum number of polling fds */
int nfds; /**< Number of active file descriptors */
enum poll_method method; /**< The current polling method */
Expand Down Expand Up @@ -221,6 +223,31 @@ static struct re *re_get(void)

#endif

#ifdef WIN32
/**
* This code emulates POSIX numbering. There is no locking,
* so zero thread-safety.
*/
static int lookup_fd_index(struct re* re, int fd) {
int i = 0;

/* First a linear search through the list of file handles
* to find existing descriptor. */
for (i = 0; i < re->nfds; i++) {
if (re->fhs[i].fd == fd)
return i;
}

/* And if nothing is found a linear search for the first
* zeroed handler */
for (i = 0; i < re->maxfds; i++) {
if (re->fhs[i].fd == 0)
return i;
}

return -1;
}
#endif

#if MAIN_DEBUG
/**
Expand All @@ -230,21 +257,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 re *re, int i, int flags)
{
const uint64_t tick = tmr_jiffies();
uint32_t diff;

DEBUG_INFO("event on fd=%d (flags=0x%02x)...\n", fd, flags);
DEBUG_INFO("event on fd=%d (flags=0x%02x)...\n", re->fhs[i].fd, flags);

re->fhs[fd].fh(flags, re->fhs[fd].arg);
re->fhs[i].fh(flags, re->fhs[i].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);
re->fhs[i].fh, re->fhs[i].arg);
}
}
#endif
Expand Down Expand Up @@ -565,9 +592,16 @@ int fd_listen(int fd, int flags, fd_h *fh, void *arg)
{
struct re *re = re_get();
int err = 0;
int i = fd;

DEBUG_INFO("fd_listen: fd=%d flags=0x%02x\n", fd, flags);


#ifdef WIN32
/* Windows file descriptors do not follow POSIX standard ranges. */
i = lookup_fd_index(re, fd);
#endif

if (fd < 0) {
DEBUG_WARNING("fd_listen: corrupt fd %d\n", fd);
return EBADF;
Expand All @@ -579,7 +613,7 @@ int fd_listen(int fd, int flags, fd_h *fh, void *arg)
return err;
}

if (fd >= re->maxfds) {
if (i >= re->maxfds) {
if (flags) {
DEBUG_WARNING("fd_listen: fd=%d flags=0x%02x"
" - Max %d fds\n",
Expand All @@ -590,12 +624,13 @@ int fd_listen(int fd, int flags, fd_h *fh, void *arg)

/* Update fh set */
if (re->fhs) {
re->fhs[fd].flags = flags;
re->fhs[fd].fh = fh;
re->fhs[fd].arg = arg;
re->fhs[i].fd = fd;
re->fhs[i].flags = flags;
re->fhs[i].fh = fh;
re->fhs[i].arg = arg;
}

re->nfds = max(re->nfds, fd+1);
re->nfds = max(re->nfds, i+1);

switch (re->method) {

Expand Down Expand Up @@ -683,15 +718,16 @@ static int fd_poll(struct re *re)
FD_ZERO(&efds);

for (i=0; i<re->nfds; i++) {
int fd = re->fhs[i].fd;
if (!re->fhs[i].fh)
continue;

if (re->fhs[i].flags & FD_READ)
FD_SET(i, &rfds);
FD_SET(fd, &rfds);
if (re->fhs[i].flags & FD_WRITE)
FD_SET(i, &wfds);
FD_SET(fd, &wfds);
if (re->fhs[i].flags & FD_EXCEPT)
FD_SET(i, &efds);
FD_SET(fd, &efds);
}

#ifdef WIN32
Expand Down Expand Up @@ -767,13 +803,15 @@ static int fd_poll(struct re *re)
#endif
#ifdef HAVE_SELECT
case METHOD_SELECT:
fd = i;
if (FD_ISSET(fd, &rfds))
flags |= FD_READ;
if (FD_ISSET(fd, &wfds))
flags |= FD_WRITE;
if (FD_ISSET(fd, &efds))
flags |= FD_EXCEPT;
fd = re->fhs[i].fd;
if (fd) {
if (FD_ISSET(fd, &rfds))
flags |= FD_READ;
if (FD_ISSET(fd, &wfds))
flags |= FD_WRITE;
if (FD_ISSET(fd, &efds))
flags |= FD_EXCEPT;
}
break;
#endif
#ifdef HAVE_EPOLL
Expand Down Expand Up @@ -838,11 +876,11 @@ static int fd_poll(struct re *re)
if (!flags)
continue;

if (re->fhs[fd].fh) {
if (re->fhs[i].fh) {
#if MAIN_DEBUG
fd_handler(re, fd, flags);
fd_handler(re, i, flags);
#else
re->fhs[fd].fh(flags, re->fhs[fd].arg);
re->fhs[i].fh(flags, re->fhs[i].arg);
#endif
}

Expand Down

0 comments on commit d3d38a4

Please sign in to comment.