X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcutil%2Fsilcschedule.c;h=5ca563035b4aa6b3008d82a48e04da47628873ac;hb=413da0f8686910f5e627393157566ae729ca99c4;hp=e0f658b08f52807e42fa93107a14f107155bbf59;hpb=382d15d447b7a95390decfa783836ae4fe255b3d;p=silc.git diff --git a/lib/silcutil/silcschedule.c b/lib/silcutil/silcschedule.c index e0f658b0..5ca56303 100644 --- a/lib/silcutil/silcschedule.c +++ b/lib/silcutil/silcschedule.c @@ -344,16 +344,17 @@ static void silc_schedule_dispatch_nontimeout(SilcSchedule schedule) SilcTask task; int i; SilcUInt32 fd, last_fd = schedule->last_fd; + SilcUInt16 revents; for (i = 0; i <= last_fd; i++) { if (schedule->fd_list[i].events == 0) continue; - fd = schedule->fd_list[i].fd; - /* First check whether this fd has task in the fd queue */ silc_mutex_lock(schedule->fd_queue->lock); + fd = schedule->fd_list[i].fd; task = silc_task_find(schedule->fd_queue, fd); + revents = schedule->fd_list[i].revents; /* If the task was found then execute its callbacks. If not then execute all generic tasks for that fd. */ @@ -363,7 +364,7 @@ static void silc_schedule_dispatch_nontimeout(SilcSchedule schedule) in the callback function, ie. it is not valid anymore. */ /* Is the task ready for reading */ - if (task->valid && schedule->fd_list[i].revents & SILC_TASK_READ) { + if (task->valid && revents & SILC_TASK_READ) { silc_mutex_unlock(schedule->fd_queue->lock); SILC_SCHEDULE_UNLOCK(schedule); task->callback(schedule, schedule->app_context, @@ -373,7 +374,7 @@ static void silc_schedule_dispatch_nontimeout(SilcSchedule schedule) } /* Is the task ready for writing */ - if (task->valid && schedule->fd_list[i].revents & SILC_TASK_WRITE) { + if (task->valid && revents & SILC_TASK_WRITE) { silc_mutex_unlock(schedule->fd_queue->lock); SILC_SCHEDULE_UNLOCK(schedule); task->callback(schedule, schedule->app_context, @@ -399,12 +400,13 @@ static void silc_schedule_dispatch_nontimeout(SilcSchedule schedule) task = schedule->generic_queue->task; while(1) { - /* Validity of the task is checked always before and after + /* Validity of the task and fd is checked always before and after execution beacuse the task might have been unregistered in the callback function, ie. it is not valid anymore. */ /* Is the task ready for reading */ - if (task->valid && schedule->fd_list[i].revents & SILC_TASK_READ) { + if (task->valid && revents & SILC_TASK_READ && + fd == schedule->fd_list[i].fd) { silc_mutex_unlock(schedule->generic_queue->lock); SILC_SCHEDULE_UNLOCK(schedule); task->callback(schedule, schedule->app_context, @@ -414,7 +416,8 @@ static void silc_schedule_dispatch_nontimeout(SilcSchedule schedule) } /* Is the task ready for writing */ - if (task->valid && schedule->fd_list[i].revents & SILC_TASK_WRITE) { + if (task->valid && revents & SILC_TASK_WRITE && + fd == schedule->fd_list[i].fd) { silc_mutex_unlock(schedule->generic_queue->lock); SILC_SCHEDULE_UNLOCK(schedule); task->callback(schedule, schedule->app_context, @@ -718,9 +721,6 @@ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd, if (!schedule->valid) return NULL; - SILC_LOG_DEBUG(("Registering new task, fd=%d type=%d priority=%d", fd, - type, priority)); - queue = SILC_SCHEDULE_GET_QUEUE(type); /* If the task is generic task, we check whether this task has already @@ -729,6 +729,9 @@ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd, if (type == SILC_TASK_GENERIC) { silc_mutex_lock(queue->lock); + SILC_LOG_DEBUG(("Registering new task, fd=%d type=%d priority=%d", fd, + type, priority)); + if (queue->task) { SilcTask task = queue->task; while(1) { @@ -754,6 +757,12 @@ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd, } newtask = silc_calloc(1, sizeof(*newtask)); + if (!newtask) + return NULL; + + SILC_LOG_DEBUG(("Registering new task %p, fd=%d type=%d priority=%d", + newtask, fd, type, priority)); + newtask->fd = fd; newtask->context = context; newtask->callback = callback; @@ -1223,7 +1232,7 @@ static int silc_schedule_task_remove(SilcTaskQueue queue, SilcTask task) return TRUE; } - SILC_LOG_DEBUG(("Removing task")); + SILC_LOG_DEBUG(("Removing task %p", task)); /* Unregister the task */ old = first;