Hiya,
Right, found the cause of the problem.
Yeech.
When aioCancel() is called, it find the tagged element, and placed
the result control structure (with it's resultp) mack onto the free list.
aioCancel() notifies aiops.c:aio_cancel() which will then mark the queued
(or currently being processed request) as cancelled.
Now, if the requestp structure gets reused again, it gets placed onto
the aiops.c request queue, but this time it's not marked as valid.
Then, if that request is then subsequently cancelled prior to the
first cancelled request being removed from the request/busy queue, all that
happens is the first request gets recancelled, the second request is still
marked as valid.
The problem happens if the second request got cancelled (really the
first recancelled) while the second was processing. If then a third request
comes in and gets the same requestp and placed onto the queue, and the second
request completes and passes its bogus requestp back to aioCheckCallbacks(),
the callback gets called with the result of the wrong operation which should
have been cancelled in the first place.
Aargh!
Patch follows:
Replace contents of aio_cancel() in aiops.c with:
int
aio_cancel(aio_result_t * resultp)
{
aio_thread_t *threadp;
aio_request_t *requestp;
int ret;
for (threadp = busy_threads_head; threadp != NULL; threadp = threadp->next)
if (threadp->donereq->resultp == resultp)
threadp->donereq->cancelled = 1;
for (requestp = request_queue_head; requestp != NULL; requestp = requestp->next)
if (requestp->resultp == resultp)
requestp->cancelled = 1;
return 0;
} /* aio_cancel */
Received on Tue Jul 29 2003 - 13:15:47 MDT
This archive was generated by hypermail pre-2.1.9 : Tue Dec 09 2003 - 16:11:43 MST