Do not uninitialize u.m.thread atomic in in finish but in free.
authorPekka Riikonen <priikone@silcnet.org>
Fri, 18 May 2007 18:14:27 +0000 (18:14 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Fri, 18 May 2007 18:14:27 +0000 (18:14 +0000)
Fixed Symbian wakeup synchronization.

CHANGES
lib/silcutil/silcfsm.c
lib/silcutil/symbian/silcsymbianscheduler.cpp
lib/silcutil/symbian/silcsymbiansocketstream.cpp

diff --git a/CHANGES b/CHANGES
index 2ab7eafa0ba654c1ab4afc171c1da10ef81cea04..4725f4df9d1ee46fd441aba5856372654636394a 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,13 @@
+Fri May 18 21:10:38 EEST 2007  Pekka Riikonen <priikone@silcnet.org>
+
+       * Do not uninitialize u.m.threads atomic int in finish but in
+         free.  Fixes crash on any platform using atomic operations
+         using mutexes (like Symbian).  Affected file is
+         lib/silcutil/silcfsm.c.
+
+       * Fixes Symbian scheduler wakeup synchronization.  Affected file
+         is lib/silcutil/symbian/silcsymbianscheduler.c.
+
 Fri May 18 18:10:36 EEST 2007  Pekka Riikonen <priikone@silcnet.org>
 
        * Fixed nickname formatting to handle already formatted nicknames
index 5139c0cd7f7be2f2c0f7b45f1e76dd1d7752da8d..f22540cd0af5ea2800a1127e56a3b9cb5e57edbb 100644 (file)
@@ -151,6 +151,9 @@ SILC_TASK_CALLBACK(silc_fsm_free_final)
   if (f->thread && f->u.t.event)
     silc_fsm_event_free(f->u.t.event);
 
+  if (!f->thread)
+    silc_atomic_uninit32(&f->u.m.threads);
+
   silc_free(f);
 }
 
@@ -485,7 +488,6 @@ SILC_TASK_CALLBACK(silc_fsm_finish_fsm)
       silc_mutex_free(fsm->u.m.lock);
       fsm->u.m.lock = NULL;
     }
-    silc_atomic_uninit32(&fsm->u.m.threads);
 
     /* Call the destructor callback. */
     if (fsm->destructor)
index fd1310244f84b9a6fa7aea84648686010e475a74..c61af404b0a643453d4063bfe94efc9851101b73 100644 (file)
@@ -94,7 +94,7 @@ public:
     Cancel();
   }
 
-  /* Wakeup */
+  /* Wakeup.  This is called with scheduler locked. */
   void Wakeup(TThreadId thread_id)
   {
     if (wake_signal)
@@ -113,6 +113,9 @@ public:
   {
     SILC_LOG_DEBUG(("Wakeup scheduler"));
 
+    /* We need to synchronize with calls to Wakeup() */
+    silc_mutex_lock(schedule->lock);
+
     /* Wakeup scheduler */
     timer->Cancel();
     timer->After(0);
@@ -120,16 +123,19 @@ public:
 
     iStatus = KRequestPending;
     SetActive();
+
+    silc_mutex_unlock(schedule->lock);
   }
 
   virtual void DoCancel()
   {
-
+    wake_signal = TRUE;
   }
 
   RThread thread;
   TThreadId id;
   SilcSymbianScheduler *timer;
+  SilcSchedule schedule;
   unsigned int wake_signal  : 1;
 };
 
@@ -159,6 +165,7 @@ void silc_schedule(SilcSchedule schedule)
   internal->wakeup->id = RThread().Id();
   internal->wakeup->thread.Open(internal->wakeup->id);
   internal->wakeup->timer = internal->timer;
+  internal->wakeup->schedule = schedule;
 
   /* Start Active Scheduler */
   s->Start();
@@ -188,7 +195,7 @@ int silc_poll(SilcSchedule schedule, void *context)
     return 0;
 
   if (timeout == -1)
-    timeout = 0;
+    return -2;
 
   /* Set the timeout value */
   at_timeout.HomeTime();
@@ -199,6 +206,8 @@ int silc_poll(SilcSchedule schedule, void *context)
   at_timeout += (TTimeIntervalMicroSeconds32)timeout;
 
   /* Schedule the timeout */
+  if (internal->timer->IsActive())
+    internal->timer->Cancel();
   internal->timer->At(at_timeout);
 
   /* Return special "ignore" value.  Causes the scheduler to just break
@@ -279,7 +288,11 @@ void silc_schedule_internal_signals_unblock(SilcSchedule schedule,
   /* Nothing to do */
 }
 
+#ifdef __WINSCW__
 EXPORT_C const SilcScheduleOps schedule_ops =
+#else
+const SilcScheduleOps schedule_ops =
+#endif /* __WINSCW__ */
 {
   silc_schedule_internal_init,
   silc_schedule_internal_uninit,
index cce36443ad519803c9f3bda1cfc8d68ec1275c04..b2362784d370746515bb6a6ce3d28abbdee303d1 100644 (file)
@@ -130,7 +130,8 @@ public:
     else
       s->sock->RecvFrom(inbuf, remote, 0, iStatus);
 
-    SetActive();
+    if (!IsActive())
+      SetActive();
   }
 
   /* Reading callback */