Bug 1959 - Proactor with multiple threads can cause assertion
Summary: Proactor with multiple threads can cause assertion
Status: NEW
Alias: None
Product: ACE
Classification: Unclassified
Component: ACE Core (show other bugs)
Version: 5.4
Hardware: x86 Linux
: P3 normal
Assignee: DOC Center Support List (internal)
URL:
Depends on:
Blocks: 3164
  Show dependency tree
 
Reported: 2004-10-06 11:02 CDT by Aaron Jackson
Modified: 2009-01-22 16:29 CST (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Aaron Jackson 2004-10-06 11:02:30 CDT
I was using the default config-linux.h and platform_linux.GNU, so there are no 
significant modification there.  After compiling I tried the Proactor_Test to 
see if it would work.  It aborted on an assertion that looks as follows:

Proactor_Test: ../sysdeps/pthread/aio_suspend.c:180: aio_suspend: Assertion 
`requestlist[cnt] ~= ((void *)0)' failed.

I found that its related to the # of proactor threads that performing 
handle_events_i and more specifically the # that are calling aio_suspend.  The 
sequence of events for 2 or more threads can look as follows:

Thread X: aio_read (set's up the aiocb_list_)
Thread 1: aio_suspend (with aiocb_list_ [shared])
Thread 2: aio_suspend (with aiocb_list_ [shared])
Thread 3: aio_suspend (with aiocb_list_ [shared])
Thread 1: wakes up does its completion
Thread 1: aio_read (modifying the aiocb_list_ with a new entry that is set to 
EINPROGRESS)
Thread 1: aio_suspend
Thread 2: wakes up in aio_suspend and checks the lists and discovers an item in 
its list (which is aiocb_list_) that is not known in its request_list.  Since 
the request_list entry is NULL, it throws the assertion, game over.

In short, aio_suspend isn't real happy if you modify the list underneath it.  
My solution is one I'm not really happy with, but it suits the need in the 
short term.

In ACE_POSIX_AIOCB_Proactor::handle_events_i, I create a local version of the 
aiocb list.  I then copy the items from the aiocb_list_ to this local structure 
and then call aio_suspend with that structure.  This ensures that any changes 
made to the "shared" list don't impact my thread-local list.  It'd be nicer is 
the thread-local list could be retained across invocations since that might 
become costly over time.  You should know that under the covers, aio_suspend 
also creates a list of its own (request_list and waiting_list) so I guess this 
isn't a considerable overhead considering those two implementations.