Holger, Craig,
Just saw Holger's check in email. Thanks for taking care of this!
Andrus
Holger Hoffstätte writes:
>
> Guys,
>
> I've spent some more time with the infamous RequestQueue failure and can
> confirm that Craig's comment below really describes the cause of the
> spurious failures:
>
>> I think I've figured out what's wrong, but not how to fix
>> it. If you turn on debug in log4j, it turns out that
>> "thread-4" is getting started before "thread-3", or rather,
>> the particulars of timing means that thread-4 gets a go at
>> executing before thread-3. For a failed test, the following
>> (..)
>> So, I *think* I know the fix, but not how to do it. After
>> starting thread-3, the test needs to wait for that thread to
>> be properly enqueued (loop waiting for
>> RequestQueue.getSize() to return >0 maybe?).
>
> Yes, this will stop the test from failing and is a good quick fix for both
> testQueueFull() and testWaitTimedOut(). I added the following to all tests
> after the first thread start():
>
> while (testCase1.getQueue().getSize() == 0) {
> Thread.yield(); // same as sleep(reallySmallAmount)
> }
>
> and ran everything several hundred thousand times now without a single
> failure. In order to fix the test this might really be the quickest and
> safest solution. Unfortunately I don't think it solves the root of the
> problem. :(
>
> IMHO everything should work without this manual caretaking - what if I
> really want to start() a couple of threads in quick succession and the
> queue is full? The current enqueueThread() method IMHO does two unrelated
> things (accepting/rejecting initial requests & synchronizing) so that got
> me thinking.
>
> I tried to redesign the threads' start() method and the dequeue handling
> in RequestQueue.enqueueThread() to better handle the initial
> synchronization by splitting up enqueueThread() between both
> synchronized(..) blocks: the first one went into a separate
> getRequestDequeue(String threadName) method, which will return a dequeue
> token with initial ENQUEUED status (new) or the usual QUEUE_FULL
> otherwise. enqueueThread() gets the dequeue to wait for as parameter. In
> the threads' run() method the dequeue is obtained by non-blockingly
> getting it from the queue, and enqueueThread() is subsequently only called
> if the returned dequeue isEnqueued(), otherwise the method returns without
> doing anything else. This prevents waiting for nonexisting/lingering
> threads and 'gate crashing' due to successive start()s and IMHO is more in
> line with regular token handling. Unfortunately it also changes the
> semantics of some of the other parts of the tests (result null/!null etc.)
> or introduce yet another race and therefore might need some more thinking
> through; comments very welcome. Maybe it's a dumb idea and I missed
> something essential.
>
> So, for a quick fix the manual waiting is IMHO OK and should be applied
> ASAP since the occasionally failing test really does not build confidence.
>
> all IMHO :)
> Holger
This archive was generated by hypermail 2.0.0 : Mon Dec 16 2002 - 18:24:23 EST