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:
@@ -171,6 +171,7 @@ state_needs_finish(int32 state)
|
|||||||
|
|
||||||
WaitList::WaitList(const char *name)
|
WaitList::WaitList(const char *name)
|
||||||
{
|
{
|
||||||
|
fCondition = 0;
|
||||||
fSem = create_sem(0, name);
|
fSem = create_sem(0, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,11 +193,17 @@ status_t
|
|||||||
WaitList::Wait(RecursiveLocker &locker, bigtime_t timeout, bool wakeNext)
|
WaitList::Wait(RecursiveLocker &locker, bigtime_t timeout, bool wakeNext)
|
||||||
{
|
{
|
||||||
locker.Unlock();
|
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();
|
locker.Lock();
|
||||||
if (wakeNext && status == B_OK)
|
if (status == B_OK && wakeNext)
|
||||||
Signal();
|
Signal();
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,8 +211,8 @@ WaitList::Wait(RecursiveLocker &locker, bigtime_t timeout, bool wakeNext)
|
|||||||
void
|
void
|
||||||
WaitList::Signal()
|
WaitList::Signal()
|
||||||
{
|
{
|
||||||
release_sem_etc(fSem, 1, B_DO_NOT_RESCHEDULE
|
atomic_or(&fCondition, 1);
|
||||||
| B_RELEASE_IF_WAITING_ONLY);
|
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));
|
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);
|
return posix_error(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ public:
|
|||||||
void Signal();
|
void Signal();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int32 fCondition;
|
||||||
sem_id fSem;
|
sem_id fSem;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user