MAPICDO and the Impersonation Hang

So – there’s a potential hang in the current builds of MAPICDO, but you can avoid it, so it doesn’t have to be a huge problem.

The repro scenario for the hang is this: You’ve got an application which does thread level impersonation and also uses MAPI. Your application starts up multiple threads under different user contexts, each of which log in to MAPI. Eventually, as each of these threads completes its work, you start releasing objects. Your thread hangs while releasing a message store object. If you were to attach a debugger and knew the stacks to look for, this hang would look almost identical to the hang we fixed in MAPICDO 6.5.8244, discussed here.

What’s going on here is related to how MAPI tracks connection lists. Each user context gets its own connection list, stored in shared memory and indexed using what is essentially the CRC of the SID of the user who initiated the connection. When starting, there are no connection lists being tracked. The first MAPI thread to initiate a connection builds a connection list which is stored in this shared memory. This thread then spins up a polling thread using CreateThread. No special effort is made to adjust the thread token of this helper thread, so it ends up running with the thread token of the calling process. At some point, this thread needs to access the connection lists. As long as only one connection list exists, we assume it must be the one we need and use it – everything’s fine.

The problems happen when we have a second MAPI thread under a new user context. We create a second connection list and add this to the list. The polling thread spun up for this thread now has two connection lists to choose from. It concludes that neither is appropriate because the SIDs don’t match, and ends up shutting down without doing any work. Later, the first polling thread encounters the two connection lists and ends up shutting itself down without ever signaling that it has finished its work.

This is where the main MAPI threads are now in trouble, as they will wait for those polling threads to signal completion, which will never happen because those threads are no longer running.

Fortunately, most MAPI server applications don’t work this way. Most MAPI server applications run as a single service account which has appropriate permissions to log in to the various mailboxes it needs to. So either there is no impersonation at all, or all of the MAPI threads impersonate the same user. Either way, there is no opportunity to run in to this problem.

So – if you do happen to run in to this issue, you should look in to creating a single service account to handle all your MAPI work, then reduce/eliminate your thread level impersonation.