fixed a race condition in TCP's WaitList Wait/Signal that was preventing Connect() from awake when it should. Reported by Francois Revol.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21024 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Hugo Santos 2007-05-04 18:43:30 +00:00
parent 1667315c1f
commit 62a21143be
2 changed files with 15 additions and 6 deletions

View File

@ -171,6 +171,7 @@ state_needs_finish(int32 state)
WaitList::WaitList(const char *name)
{
fCondition = 0;
fSem = create_sem(0, name);
}
@ -192,11 +193,17 @@ status_t
WaitList::Wait(RecursiveLocker &locker, bigtime_t timeout, bool wakeNext)
{
locker.Unlock();
status_t status = acquire_sem_etc(fSem, 1, B_ABSOLUTE_TIMEOUT
| B_CAN_INTERRUPT, timeout);
status_t status = B_OK;
while (status == B_OK && !atomic_test_and_set(&fCondition, 0, 1))
status = acquire_sem_etc(fSem, 1, B_ABSOLUTE_TIMEOUT | B_CAN_INTERRUPT,
timeout);
locker.Lock();
if (wakeNext && status == B_OK)
if (status == B_OK && wakeNext)
Signal();
return status;
}
@ -204,8 +211,8 @@ WaitList::Wait(RecursiveLocker &locker, bigtime_t timeout, bool wakeNext)
void
WaitList::Signal()
{
release_sem_etc(fSem, 1, B_DO_NOT_RESCHEDULE
| B_RELEASE_IF_WAITING_ONLY);
atomic_or(&fCondition, 1);
release_sem_etc(fSem, 1, B_DO_NOT_RESCHEDULE | B_RELEASE_IF_WAITING_ONLY);
}
@ -418,7 +425,8 @@ TCPEndpoint::Connect(const sockaddr *address)
}
status = _WaitForEstablished(locker, absolute_timeout(timeout));
TRACE(" Connect(): Connection complete: %s", strerror(status));
TRACE(" Connect(): Connection complete: %s (timeout was %llu)",
strerror(status), timeout);
return posix_error(status);
}

View File

@ -36,6 +36,7 @@ public:
void Signal();
private:
int32 fCondition;
sem_id fSem;
};