summaryrefslogtreecommitdiff
path: root/common/server-mainloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/server-mainloop.c')
-rw-r--r--common/server-mainloop.c77
1 files changed, 39 insertions, 38 deletions
diff --git a/common/server-mainloop.c b/common/server-mainloop.c
index fcd471d..1ba5085 100644
--- a/common/server-mainloop.c
+++ b/common/server-mainloop.c
@@ -45,6 +45,7 @@ typedef struct _socket_callback {
int fd;
server_socket_callback callback;
void *arg;
+ int closed;
struct _socket_callback *next;
} socket_callback;
@@ -54,6 +55,7 @@ typedef struct _timer_callback {
struct timeval interval;
server_timer_callback callback;
void* arg;
+ int closed;
struct _timer_callback *next;
} timer_callback;
@@ -166,35 +168,33 @@ add_timer (int ms, int oneshot, server_timer_callback callback, void *arg)
return 0;
}
-static timer_callback*
-remove_timer(timer_callback *timcb)
+static void
+remove_closed (void)
{
- timer_callback *cb;
- timer_callback *next;
-
- if (!ctx.timers)
- return NULL;
-
- /* First in list */;
- if (ctx.timers == timcb) {
- cb = ctx.timers;
- ctx.timers = ctx.timers->next;
- free (cb);
- return ctx.timers;
+ timer_callback **tcb, *timcb;
+ socket_callback **scb, *sockcb;
+
+ for (tcb = &ctx.timers; *tcb; ) {
+ timcb = *tcb;
+ if (timcb->closed) {
+ *tcb = timcb->next;
+ free (timcb);
+ continue;
+ } else {
+ tcb = &timcb->next;
+ }
}
- /* One ahead processing of rest */
- for (cb = ctx.timers; cb->next; cb = cb->next) {
- if(cb->next == timcb) {
- next = cb->next->next;
- free (cb->next);
- cb->next = next;
- return cb->next;
+ for (scb = &ctx.callbacks; *scb; ) {
+ sockcb = *scb;
+ if (sockcb->closed) {
+ *scb = sockcb->next;
+ free (sockcb);
+ continue;
+ } else {
+ scb = &sockcb->next;
}
}
-
- /* Couldn't remove, return self */
- return timcb;
}
void
@@ -248,7 +248,7 @@ server_run (void)
struct timeval *timeout;
struct timeval tv, current;
timer_callback *timcb;
- socket_callback *sockcb, *socknx;
+ socket_callback *sockcb;
fd_set rfds, wfds;
int r;
@@ -268,9 +268,12 @@ server_run (void)
return -1;
/* Cycle through timers */
- for (timcb = ctx.timers; timcb; ) {
+ for (timcb = ctx.timers; timcb; timcb = timcb->next) {
assert (timcb->callback);
+ if (timcb->closed)
+ continue;
+
/* Call any timers that have already passed */
if (timeval_compare (&current, &timcb->at) >= 0) {
@@ -287,7 +290,7 @@ server_run (void)
/* Otherwise remove it. Either one shot, or returned 0 */
} else {
- timcb = remove_timer (timcb);
+ timcb->closed = 1;
continue;
}
}
@@ -295,8 +298,6 @@ server_run (void)
/* Get soonest timer */
if (!timeout || timeval_compare (&timcb->at, timeout) < 0)
timeout = &timcb->at;
-
- timcb = timcb->next;
}
/* Convert to an offset */
@@ -309,6 +310,10 @@ server_run (void)
if (ctx.stopped)
continue;
+ remove_closed ();
+ if (!ctx.callbacks && !ctx.timers)
+ break;
+
/* fprintf(stderr, "selecting with timeout: ");
timeval_dump(timeout);
fprintf(stderr, "\n"); */
@@ -329,17 +334,16 @@ server_run (void)
if(r == 0)
continue;
- for (sockcb = ctx.callbacks; sockcb; ) {
+ for (sockcb = ctx.callbacks; sockcb; sockcb = sockcb->next) {
assert (sockcb->fd != -1);
- socknx = sockcb->next;
+ if (sockcb->closed)
+ continue;
/* Call any that are set */
if (FD_ISSET (sockcb->fd, &rfds))
(sockcb->callback) (sockcb->fd, SERVER_READ, sockcb->arg);
if (FD_ISSET (sockcb->fd, &wfds))
(sockcb->callback) (sockcb->fd, SERVER_WRITE, sockcb->arg);
-
- sockcb = socknx;
}
}
@@ -405,17 +409,14 @@ server_unwatch (int fd)
/* First in list */;
if (ctx.callbacks->fd == fd) {
- cb = ctx.callbacks;
- ctx.callbacks = cb->next;
- free (cb);
+ ctx.callbacks->closed = 1;
return;
}
/* One ahead processing of rest */
for (cb = ctx.callbacks; cb->next; cb = cb->next) {
if (cb->next->fd == fd) {
- cb->next = cb->next->next;
- free (cb->next);
+ cb->next->closed = 1;
return;
}
}