silc_stream_set_notifier and silc_schedule_set_listen_fd now
authorPekka Riikonen <priikone@silcnet.org>
Tue, 23 Jan 2007 14:47:00 +0000 (14:47 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Tue, 23 Jan 2007 14:47:00 +0000 (14:47 +0000)
returns error condition.
Fixed FD task addition when FD task already exists.

lib/silcutil/silcfdstream.c
lib/silcutil/silcschedule.c
lib/silcutil/silcschedule.h
lib/silcutil/silcsocketstream.c
lib/silcutil/silcstream.c
lib/silcutil/silcstream.h
lib/silcutil/symbian/silcsymbiansocketstream.cpp
lib/silcutil/unix/silcunixnet.c
lib/silcutil/unix/silcunixschedule.c
lib/silcutil/unix/silcunixsocketstream.c

index cbd837aa9c07f4a7d5289cc8733b91bd431f1406..67ad3269c7f514d2e1ee1f5ccbc59b81877ee92c 100644 (file)
@@ -233,10 +233,12 @@ SilcBool silc_fd_stream_close(SilcStream stream)
   if (fd_stream->fd1 > 0) {
     silc_file_close(fd_stream->fd1);
     silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd1);
+    silc_schedule_task_del_by_fd(fd_stream->schedule, fd_stream->fd1);
   }
   if (fd_stream->fd2 > 0 && fd_stream->fd2 != fd_stream->fd1) {
     silc_file_close(fd_stream->fd2);
     silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd2);
+    silc_schedule_task_del_by_fd(fd_stream->schedule, fd_stream->fd2);
   }
 
   return TRUE;
@@ -246,20 +248,16 @@ SilcBool silc_fd_stream_close(SilcStream stream)
 
 void silc_fd_stream_destroy(SilcStream stream)
 {
-  SilcFDStream fd_stream = stream;
-
   silc_fd_stream_close(stream);
-  silc_schedule_task_del_by_fd(fd_stream->schedule, fd_stream->fd1);
-  silc_schedule_task_del_by_fd(fd_stream->schedule, fd_stream->fd2);
   silc_free(stream);
 }
 
 /* Sets stream notification callback for the stream */
 
-void silc_fd_stream_notifier(SilcStream stream,
-                            SilcSchedule schedule,
-                            SilcStreamNotifier callback,
-                            void *context)
+SilcBool silc_fd_stream_notifier(SilcStream stream,
+                                SilcSchedule schedule,
+                                SilcStreamNotifier callback,
+                                void *context)
 {
   SilcFDStream fd_stream = stream;
 
@@ -288,7 +286,11 @@ void silc_fd_stream_notifier(SilcStream stream,
   } else {
     silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd1);
     silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd2);
+    silc_schedule_task_del_by_fd(fd_stream->schedule, fd_stream->fd1);
+    silc_schedule_task_del_by_fd(fd_stream->schedule, fd_stream->fd2);
   }
+
+  return TRUE;
 }
 
 /* Return schedule */
index aa648e3908eb5bb58be946ef27ae4d846fddf1ff..5d1760cc150320a26323647f83b4cc94a86fcf66 100644 (file)
@@ -600,20 +600,30 @@ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd,
     /* Check if fd is already added */
     if (silc_unlikely(silc_hash_table_find(schedule->fd_queue,
                                           SILC_32_TO_PTR(fd),
-                                          NULL, (void **)&task)))
-      goto out;
+                                          NULL, (void **)&task))) {
+      if (task->valid) {
+        task = NULL;
+        goto out;
+      }
+
+      /* Remove invalid task.  We must have unique fd key to hash table. */
+      silc_schedule_task_remove(schedule, task);
+    }
 
     /* Check max tasks */
     if (silc_unlikely(schedule->max_tasks > 0 &&
                      silc_hash_table_count(schedule->fd_queue) >=
                      schedule->max_tasks)) {
       SILC_LOG_WARNING(("Scheduler task limit reached: cannot add new task"));
+      task = NULL;
       goto out;
     }
 
     ftask = silc_calloc(1, sizeof(*ftask));
-    if (silc_unlikely(!ftask))
+    if (silc_unlikely(!ftask)) {
+      task = NULL;
       goto out;
+    }
 
     SILC_LOG_DEBUG(("New fd task %p fd=%d", ftask, fd));
 
@@ -625,9 +635,17 @@ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd,
     ftask->fd = fd;
 
     /* Add task and schedule it */
-    silc_hash_table_add(schedule->fd_queue, SILC_32_TO_PTR(fd), ftask);
-    schedule_ops.schedule_fd(schedule, schedule->internal, ftask,
-                            ftask->events);
+    if (!silc_hash_table_add(schedule->fd_queue, SILC_32_TO_PTR(fd), ftask)) {
+      silc_free(ftask);
+      task = NULL;
+      goto out;
+    }
+    if (!schedule_ops.schedule_fd(schedule, schedule->internal, 
+                                 ftask, ftask->events)) {
+      silc_hash_table_del(schedule->fd_queue, SILC_32_TO_PTR(fd));
+      task = NULL;
+      goto out;
+    }
 
     task = (SilcTask)ftask;
 
@@ -689,8 +707,10 @@ void silc_schedule_task_del_by_fd(SilcSchedule schedule, SilcUInt32 fd)
   /* fd is unique, so there is only one task with this fd in the table */
   if (silc_likely(silc_hash_table_find(schedule->fd_queue,
                                       SILC_32_TO_PTR(fd), NULL,
-                                      (void **)&task)))
+                                      (void **)&task))) {
+    SILC_LOG_DEBUG(("Deleting task %p", task));
     task->valid = FALSE;
+  }
 
   SILC_SCHEDULE_UNLOCK(schedule);
 
@@ -793,20 +813,23 @@ void silc_schedule_task_del_by_all(SilcSchedule schedule, int fd,
    directly if wanted. This can be called multiple times for one file
    descriptor to set different iomasks. */
 
-void silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd,
-                                SilcTaskEvent mask, SilcBool send_events)
+SilcBool silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd,
+                                    SilcTaskEvent mask, SilcBool send_events)
 {
   SilcTaskFd task;
 
   if (silc_unlikely(!schedule->valid))
-    return;
+    return FALSE;
 
   SILC_SCHEDULE_LOCK(schedule);
 
   if (silc_hash_table_find(schedule->fd_queue, SILC_32_TO_PTR(fd),
                           NULL, (void **)&task)) {
+    if (!schedule_ops.schedule_fd(schedule, schedule->internal, task, mask)) {
+      SILC_SCHEDULE_UNLOCK(schedule);
+      return FALSE;
+    }
     task->events = mask;
-    schedule_ops.schedule_fd(schedule, schedule->internal, task, mask);
     if (silc_unlikely(send_events) && mask) {
       task->revents = mask;
       silc_schedule_dispatch_fd(schedule);
@@ -814,9 +837,11 @@ void silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd,
   }
 
   SILC_SCHEDULE_UNLOCK(schedule);
+
+  return TRUE;
 }
 
-/* Returns the file descriptors current requested event mask. */
+/* Returns the file descriptor's current requested event mask. */
 
 SilcTaskEvent silc_schedule_get_fd_events(SilcSchedule schedule,
                                          SilcUInt32 fd)
index 4dc15c50c928335fd84aec73e45c103e9031baac..32557df955290a00467e7526e0335d35e56ee23b 100644 (file)
@@ -375,6 +375,9 @@ void *silc_schedule_get_context(SilcSchedule schedule);
  *    handle.  To receive events for the file descriptor set the correct
  *    request events with silc_schedule_set_listen_fd function.
  *
+ *    The task will be initially set for SILC_TASK_READ events.  Setting that
+ *    event immediately after this call returns is not necessary.
+ *
  ***/
 #define silc_schedule_task_add_fd(schedule, fd, callback, context)     \
   silc_schedule_task_add(schedule, fd, callback, context, 0, 0,        SILC_TASK_FD)
@@ -530,9 +533,10 @@ void silc_schedule_task_del_by_all(SilcSchedule schedule, int fd,
  *
  * SYNOPSIS
  *
- *    void silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd,
- *                                     SilcTaskEvent mask,
- *                                     SilcBool send_events);
+ *    SilcBool silc_schedule_set_listen_fd(SilcSchedule schedule, 
+ *                                         SilcUInt32 fd,
+ *                                         SilcTaskEvent mask,
+ *                                         SilcBool send_events);
  *
  * DESCRIPTION
  *
@@ -550,9 +554,12 @@ void silc_schedule_task_del_by_all(SilcSchedule schedule, int fd,
  *    after the event occurs in reality.  In normal cases the `send_events'
  *    is set to FALSE.
  *
+ *    Returns FALSE if the operation could not performed and TRUE if it
+ *    was a success.
+ *
  ***/
-void silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd,
-                                SilcTaskEvent mask, SilcBool send_events);
+SilcBool silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd,
+                                    SilcTaskEvent mask, SilcBool send_events);
 
 /****f* silcutil/SilcScheduleAPI/silc_schedule_get_fd_events
  *
index c320644737440f01c2991fe79636de0fea0a493e..a617f45c2fffb3d376fb19e55cdd3445a93a2b66 100644 (file)
@@ -34,10 +34,10 @@ int silc_socket_udp_stream_write(SilcStream stream, const unsigned char *data,
                                 SilcUInt32 data_len);
 SilcBool silc_socket_stream_close(SilcStream stream);
 void silc_socket_stream_destroy(SilcStream stream);
-void silc_socket_stream_notifier(SilcStream stream,
-                                SilcSchedule schedule,
-                                SilcStreamNotifier callback,
-                                void *context);
+SilcBool silc_socket_stream_notifier(SilcStream stream,
+                                    SilcSchedule schedule,
+                                    SilcStreamNotifier callback,
+                                    void *context);
 SilcSchedule silc_socket_stream_get_schedule(SilcStream stream);
 
 /* Internal async host lookup context. */
@@ -165,7 +165,7 @@ silc_socket_tcp_stream_create(SilcSocket sock, SilcBool lookup,
     return NULL;
   }
 
-  SILC_LOG_DEBUG(("Creating TCP socket stream %p", stream));
+  SILC_LOG_DEBUG(("Creating TCP socket stream %p, sock %lu", stream, sock));
 
   stream->ops = &silc_socket_stream_ops;
   stream->sock = sock;
index 7b8b08af36bc39ed014b98c59a952a2711261d77..af4789dfeeb495054b71c3f72137a55038b91ba9 100644 (file)
@@ -49,11 +49,11 @@ void silc_stream_destroy(SilcStream stream)
   h->ops->destroy(stream);
 }
 
-void silc_stream_set_notifier(SilcStream stream, SilcSchedule schedule,
-                             SilcStreamNotifier notifier, void *context)
+SilcBool silc_stream_set_notifier(SilcStream stream, SilcSchedule schedule,
+                                 SilcStreamNotifier notifier, void *context)
 {
   SilcStreamHeader h = stream;
-  h->ops->notifier(stream, schedule, notifier, context);
+  return h->ops->notifier(stream, schedule, notifier, context);
 }
 
 SilcSchedule silc_stream_get_schedule(SilcStream stream)
index efa161f1886b5cf1091168a1299a69afab70d647..4c8c0eb613985098a6f53ad73adfde0cef1a1396 100644 (file)
@@ -147,9 +147,10 @@ typedef struct {
   /* This is called to set a notifier callback to the stream and schedule
      the stream.  Stream should not be scheduled before calling this
      function.  If stream does not need scheduler then the scheduler can
-     be ignored.  This is called when silc_stream_set_notifier was called. */
-  void (*notifier)(SilcStream stream, SilcSchedule schedule,
-                  SilcStreamNotifier callback, void *context);
+     be ignored.  This is called when silc_stream_set_notifier was called.
+     Returns FALSE if the stream could not be scheduled. */
+  SilcBool (*notifier)(SilcStream stream, SilcSchedule schedule,
+                      SilcStreamNotifier callback, void *context);
 
   /* This is called to return the associated scheduler, if set.  This is
      called when silc_stream_get_schedule was called. */
@@ -208,7 +209,7 @@ int silc_stream_write(SilcStream stream, const unsigned char *data,
  *    Closes the stream indicated by `stream'.  No data can be read or written
  *    to the stream after calling this function.  Return TRUE if the stream
  *    could be closed.  If action is taken on closed stream the notifier
- *    callback will be called with an error status.
+ *    callback may be called with an error status.
  *
  ***/
 SilcBool silc_stream_close(SilcStream stream);
@@ -234,25 +235,30 @@ void silc_stream_destroy(SilcStream stream);
  *
  * SYNOPSIS
  *
- *    void silc_stream_set_notifier(SilcStream stream,
- *                                  SilcSchedule schedule,
- *                                  SilcStreamNotifier notifier,
- *                                  void *context);
+ *    SilcBool silc_stream_set_notifier(SilcStream stream,
+ *                                      SilcSchedule schedule,
+ *                                      SilcStreamNotifier notifier,
+ *                                      void *context);
  *
  * DESCRIPTION
  *
  *    Set a notifier callback for the stream indicated by `stream' to be called
  *    when some action takes place on the stream.  This effectively means
  *    scheduling the stream for various actions, that then eventually will
- *    be delivered to caller in the `notifier'  callback.  It is called for
+ *    be delivered to caller in the `notifier' callback.  It is called for
  *    example when data is available for reading or writing, or if an error
  *    occurs.  This can be called at any time for valid stream.
+ *
  *    If `notifier' is set to NULL no callback will be called for the stream,
  *    and the stream is not scheduled anymore.
  *
+ *    This function returns FALSE if the `schedule' was provided and the
+ *    stream could not be scheduled.  The actual API for `stream' may provide
+ *    access to the actual error information.  Returns TRUE on success.
+ *
  ***/
-void silc_stream_set_notifier(SilcStream stream, SilcSchedule schedule,
-                             SilcStreamNotifier notifier, void *context);
+SilcBool silc_stream_set_notifier(SilcStream stream, SilcSchedule schedule,
+                                 SilcStreamNotifier notifier, void *context);
 
 /****f* silcutil/SilcStreamAPI/silc_stream_get_schedule
  *
index 3fcb7cec500f3e7af52aa33b32c511810408ea5d..7d791169f0615ee24269c068b86821175d75ccb8 100644 (file)
@@ -384,10 +384,10 @@ void silc_socket_stream_destroy(SilcStream stream)
 
 /* Sets stream notification callback for the stream */
 
-void silc_socket_stream_notifier(SilcStream stream,
-                                SilcSchedule schedule,
-                                SilcStreamNotifier callback,
-                                void *context)
+SilcBool silc_socket_stream_notifier(SilcStream stream,
+                                    SilcSchedule schedule,
+                                    SilcStreamNotifier callback,
+                                    void *context)
 {
   SilcSocketStream socket_stream = (SilcSocketStream)stream;
   SilcSymbianSocket *s = (SilcSymbianSocket *)socket_stream->sock;
@@ -400,4 +400,6 @@ void silc_socket_stream_notifier(SilcStream stream,
   socket_stream->notifier = callback;
   socket_stream->notifier_context = context;
   socket_stream->schedule = schedule;
+
+  return TRUE;
 }
index 1ce203811c0c249b5a8baa33915391abac663d8a..f7ddb18db0449e86f623301246c150b295856dc2 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2006 Pekka Riikonen
+  Copyright (C) 1997 - 2007 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
@@ -489,7 +489,7 @@ SILC_FSM_STATE(silc_net_connect_st_start)
   if (conn->aborted) {
     /** Aborted */
     silc_fsm_next(fsm, silc_net_connect_st_finish);
-    SILC_FSM_CONTINUE;
+    return SILC_FSM_CONTINUE;
   }
 
   /* Do host lookup */
@@ -502,14 +502,14 @@ SILC_FSM_STATE(silc_net_connect_st_start)
     /** Network unreachable */
     conn->status = SILC_NET_HOST_UNREACHABLE;
     silc_fsm_next(fsm, silc_net_connect_st_finish);
-    SILC_FSM_CONTINUE;
+    return SILC_FSM_CONTINUE;
   }
 
   /* Set sockaddr for this connection */
   if (!silc_net_set_sockaddr(&desthost, conn->ip_addr, conn->port)) {
     /** Sockaddr failed */
     silc_fsm_next(fsm, silc_net_connect_st_finish);
-    SILC_FSM_CONTINUE;
+    return SILC_FSM_CONTINUE;
   }
 
   /* Create the connection socket */
@@ -525,7 +525,7 @@ SILC_FSM_STATE(silc_net_connect_st_start)
     /** Cannot create socket */
     SILC_LOG_ERROR(("Cannot create socket: %s", strerror(errno)));
     silc_fsm_next(fsm, silc_net_connect_st_finish);
-    SILC_FSM_CONTINUE;
+    return SILC_FSM_CONTINUE;
   }
 
   /* Bind to the local address if provided */
@@ -559,7 +559,7 @@ SILC_FSM_STATE(silc_net_connect_st_start)
       /** Cannot connect to remote host */
       SILC_LOG_ERROR(("Cannot connect to remote host: %s", strerror(errno)));
       silc_fsm_next(fsm, silc_net_connect_st_finish);
-      SILC_FSM_CONTINUE;
+      return SILC_FSM_CONTINUE;
     }
   }
 
@@ -581,7 +581,7 @@ SILC_FSM_STATE(silc_net_connect_st_start)
   silc_schedule_set_listen_fd(silc_fsm_get_schedule(fsm), sock,
                              SILC_TASK_WRITE, FALSE);
   SILC_FSM_EVENT_WAIT(&conn->event);
-  SILC_FSM_CONTINUE;
+  return SILC_FSM_CONTINUE;
 }
 
 static void silc_net_connect_wait_stream(SilcSocketStreamStatus status,
@@ -602,7 +602,7 @@ SILC_FSM_STATE(silc_net_connect_st_connected)
   if (conn->aborted) {
     /** Aborted */
     silc_fsm_next(fsm, silc_net_connect_st_finish);
-    SILC_FSM_CONTINUE;
+    return SILC_FSM_CONTINUE;
   }
 
   ret = silc_net_get_socket_opt(conn->sock, SOL_SOCKET, SO_ERROR,
@@ -618,7 +618,7 @@ SILC_FSM_STATE(silc_net_connect_st_connected)
       conn->retry--;
       silc_net_close_connection(conn->sock);
       silc_fsm_next(fsm, silc_net_connect_st_start);
-      SILC_FSM_CONTINUE;
+      return SILC_FSM_CONTINUE;
     }
 
 #if defined(ECONNREFUSED)
@@ -637,7 +637,7 @@ SILC_FSM_STATE(silc_net_connect_st_connected)
     /** Connecting failed */
     SILC_LOG_DEBUG(("Connecting failed"));
     silc_fsm_next(fsm, silc_net_connect_st_finish);
-    SILC_FSM_CONTINUE;
+    return SILC_FSM_CONTINUE;
   }
 
   /** Connection created */
@@ -655,7 +655,7 @@ SILC_FSM_STATE(silc_net_connect_st_stream)
   if (conn->aborted) {
     /** Aborted */
     silc_fsm_next(fsm, silc_net_connect_st_finish);
-    SILC_FSM_CONTINUE;
+    return SILC_FSM_CONTINUE;
   }
 
   if (conn->stream_status != SILC_SOCKET_OK) {
@@ -667,7 +667,7 @@ SILC_FSM_STATE(silc_net_connect_st_stream)
     else
       conn->status = SILC_NET_ERROR;
     silc_fsm_next(fsm, silc_net_connect_st_finish);
-    SILC_FSM_CONTINUE;
+    return SILC_FSM_CONTINUE;
   }
 
   /* Set stream information */
@@ -676,10 +676,10 @@ SILC_FSM_STATE(silc_net_connect_st_stream)
                              conn->ip_addr, conn->ip_addr, conn->port);
 
   /** Stream created successfully */
-  SILC_LOG_DEBUG(("Connected successfully"));
+  SILC_LOG_DEBUG(("Connected successfully, sock %d", conn->sock));
   conn->status = SILC_NET_OK;
   silc_fsm_next(fsm, silc_net_connect_st_finish);
-  SILC_FSM_CONTINUE;
+  return SILC_FSM_CONTINUE;
 }
 
 SILC_FSM_STATE(silc_net_connect_st_finish)
@@ -695,7 +695,7 @@ SILC_FSM_STATE(silc_net_connect_st_finish)
       silc_async_free(conn->sop);
   }
 
-  SILC_FSM_FINISH;
+  return SILC_FSM_FINISH;
 }
 
 static void silc_net_connect_abort(SilcAsyncOperation op, void *context)
@@ -774,6 +774,7 @@ SilcAsyncOperation silc_net_tcp_connect(const char *local_ip_addr,
 
 void silc_net_close_connection(int sock)
 {
+  SILC_LOG_DEBUG(("Closing sock %d", sock));
   close(sock);
 }
 
index 14fd31efd6c764ca0434b2bb8cb74f55c57f2bd1..df080730f30cfc48965b8a972c87f0891c8ae266 100644 (file)
@@ -267,31 +267,42 @@ SilcBool silc_schedule_internal_schedule_fd(SilcSchedule schedule,
   struct epoll_event event;
 
   if (!internal)
-    return FALSE;
+    return TRUE;
+
+  SILC_LOG_DEBUG(("Scheduling fd %lu, mask %x", task->fd, event_mask));
 
   event.events = 0;
-  if (task->events & SILC_TASK_READ)
+  if (event_mask & SILC_TASK_READ)
     event.events |= (EPOLLIN | EPOLLPRI);
-  if (task->events & SILC_TASK_WRITE)
+  if (event_mask & SILC_TASK_WRITE)
     event.events |= EPOLLOUT;
 
   /* Zero mask unschedules task */
   if (silc_unlikely(!event.events)) {
-    epoll_ctl(internal->epfd, EPOLL_CTL_DEL, task->fd, &event);
+    if (epoll_ctl(internal->epfd, EPOLL_CTL_DEL, task->fd, &event)) {
+      SILC_LOG_DEBUG(("epoll_ctl (DEL): %s", strerror(errno)));
+      return FALSE;
+    }
     return TRUE;
   }
 
   /* Schedule the task */
   if (silc_unlikely(!task->scheduled)) {
     event.data.ptr = task;
-    epoll_ctl(internal->epfd, EPOLL_CTL_ADD, task->fd, &event);
+    if (epoll_ctl(internal->epfd, EPOLL_CTL_ADD, task->fd, &event)) {
+      SILC_LOG_DEBUG(("epoll_ctl (ADD): %s", strerror(errno)));
+      return FALSE;
+    }
     task->scheduled = TRUE;
     return TRUE;
   }
 
   /* Schedule for specific mask */
   event.data.ptr = task;
-  epoll_ctl(internal->epfd, EPOLL_CTL_MOD, task->fd, &event);
+  if (epoll_ctl(internal->epfd, EPOLL_CTL_MOD, task->fd, &event)) {
+    SILC_LOG_DEBUG(("epoll_ctl (MOD): %s", strerror(errno)));
+    return FALSE;
+  }
 #endif /* HAVE_EPOLL_WAIT */
   return TRUE;
 }
index 046c795c7e247b82d3212fe555d84d5f68098387..a50f3e464b44c9e3e26ff5a0c45ca892ffbdef5d 100644 (file)
@@ -254,6 +254,7 @@ SilcBool silc_socket_stream_close(SilcStream stream)
   SilcSocketStream socket_stream = stream;
 
   silc_schedule_unset_listen_fd(socket_stream->schedule, socket_stream->sock);
+  silc_schedule_task_del_by_fd(socket_stream->schedule, socket_stream->sock);
   silc_net_close_connection(socket_stream->sock);
 
   return TRUE;
@@ -290,10 +291,10 @@ void silc_socket_stream_destroy(SilcStream stream)
 
 /* Sets stream notification callback for the stream */
 
-void silc_socket_stream_notifier(SilcStream stream,
-                                SilcSchedule schedule,
-                                SilcStreamNotifier callback,
-                                void *context)
+SilcBool silc_socket_stream_notifier(SilcStream stream,
+                                    SilcSchedule schedule,
+                                    SilcStreamNotifier callback,
+                                    void *context)
 {
   SilcSocketStream socket_stream = stream;
 
@@ -305,19 +306,24 @@ void silc_socket_stream_notifier(SilcStream stream,
 
   if (socket_stream->notifier) {
     /* Add the socket to scheduler.  Safe to call if already added. */
-    silc_schedule_task_add_fd(socket_stream->schedule, socket_stream->sock,
-                             silc_socket_stream_io, socket_stream);
+    if (!silc_schedule_task_add_fd(socket_stream->schedule,
+                                  socket_stream->sock,
+                                  silc_socket_stream_io, socket_stream))
+      return FALSE;
 
     /* Initially set socket for reading */
-    silc_schedule_set_listen_fd(socket_stream->schedule, socket_stream->sock,
-                               SILC_TASK_READ, FALSE);
-    silc_schedule_wakeup(socket_stream->schedule);
+    if (!silc_schedule_set_listen_fd(socket_stream->schedule,
+                                    socket_stream->sock,
+                                    SILC_TASK_READ, FALSE))
+      return FALSE;
   } else {
     /* Unschedule the socket */
     silc_schedule_unset_listen_fd(socket_stream->schedule,
                                  socket_stream->sock);
     silc_schedule_task_del_by_fd(socket_stream->schedule,
                                 socket_stream->sock);
-    silc_schedule_wakeup(socket_stream->schedule);
   }
+
+  silc_schedule_wakeup(socket_stream->schedule);
+  return TRUE;
 }