Merged silc_1_0_branch to trunk.
[silc.git] / lib / silcutil / silcschedule.c
index 515d3a9fc8134e92567fb407957f1c0c3cd30510..5ca563035b4aa6b3008d82a48e04da47628873ac 100644 (file)
@@ -1,16 +1,15 @@
 /*
 
-  silcschedule.c
+  silcschedule.c 
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1998 - 2001 Pekka Riikonen
+  Copyright (C) 1998 - 2002 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-  
+  the Free Software Foundation; version 2 of the License.
+
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
@@ -275,16 +274,16 @@ bool silc_schedule_uninit(SilcSchedule schedule)
     return FALSE;
 
   /* Dispatch all timeouts before going away */
+  SILC_SCHEDULE_LOCK(schedule);
   silc_mutex_lock(schedule->timeout_queue->lock);
   silc_schedule_dispatch_timeout(schedule, TRUE);
   silc_mutex_unlock(schedule->timeout_queue->lock);
+  SILC_SCHEDULE_UNLOCK(schedule);
 
   /* Deliver signals before going away */
   if (schedule->signal_tasks) {
-    SILC_SCHEDULE_UNLOCK(schedule);
     silc_schedule_internal_signals_call(schedule->internal, schedule);
     schedule->signal_tasks = FALSE;
-    SILC_SCHEDULE_LOCK(schedule);
   }
 
   /* Unregister all tasks */
@@ -343,18 +342,19 @@ void silc_schedule_stop(SilcSchedule schedule)
 static void silc_schedule_dispatch_nontimeout(SilcSchedule schedule)
 {
   SilcTask task;
-  int i, last_fd = schedule->last_fd;
-  SilcUInt32 fd;
+  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. */
@@ -364,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,
@@ -374,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,
@@ -400,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,
@@ -415,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,
@@ -719,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
@@ -730,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) {
@@ -755,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;
@@ -1224,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;