X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcutil%2Fsilcfsm.c;h=0098bf2f551ade169311ca8b438769be5e09719c;hb=88e6f819b977bffc3d838988401cc89b5efef6b6;hp=aff9a77edf5e1cf8d7c053083289e06fcf706475;hpb=0b06dea933045648e8e1c7376d7b71f473f6665c;p=silc.git diff --git a/lib/silcutil/silcfsm.c b/lib/silcutil/silcfsm.c index aff9a77e..0098bf2f 100644 --- a/lib/silcutil/silcfsm.c +++ b/lib/silcutil/silcfsm.c @@ -560,9 +560,13 @@ SilcUInt32 silc_fsm_event_wait(SilcFSMEvent event, void *fsm) SILC_LOG_DEBUG(("Received event %p", event)); - /* It is possible that this FSM is in the list so remove it */ + /* Remove from waiting */ silc_list_del(event->waiters, fsm); - event->value--; + + /* Decrease the counter only after all waiters have acquired the signal. */ + if (!silc_list_count(event->waiters)) + event->value--; + silc_mutex_unlock(lock); return 1; } @@ -634,12 +638,12 @@ SILC_TASK_CALLBACK(silc_fsm_signal) SilcMutex lock = p->event->fsm->u.m.lock; SilcFSM fsm; - /* We have to check couple of things before delivering the signal. */ + /* We have to check for couple of things before delivering the signal. */ /* If the event value has went to zero while we've been waiting this callback, the event has been been signalled already. It can happen when using real threads because the FSM may not be in waiting state - when the sempahore is posted. */ + when the event is signalled. */ silc_mutex_lock(lock); if (!p->event->value) { silc_mutex_unlock(lock); @@ -648,7 +652,9 @@ SILC_TASK_CALLBACK(silc_fsm_signal) return; } - /* If the waiter is not waiting anymore, don't deliver the signal */ + /* If the waiter is not waiting anymore, don't deliver the signal. It + can happen if there were multiple signallers and the waiter went away + after the first signal. */ silc_list_start(p->event->waiters); while ((fsm = silc_list_get(p->event->waiters))) if (fsm == p->fsm) @@ -685,7 +691,7 @@ void silc_fsm_event_signal(SilcFSMEvent event) event->value++; silc_list_start(event->waiters); - while ((fsm = silc_list_get(event->waiters)) != SILC_LIST_END) { + while ((fsm = silc_list_get(event->waiters))) { if (fsm->event) { silc_schedule_task_del_by_all(fsm->schedule, 0, silc_fsm_event_timedout, fsm);