I've made a small modification to the (native) test app. What I've discovered is that when we run many threads (each of which creates and uses its own CMAPIEx object) which call the SendTest function in a loop to send multiple email messages, he following behavior is observed.
- If the message has one or two recipient addresses all threads send all messages reliably and consistently when we run the test over and over.
- If the message has three or more To, CC or BCC recipients, then all of the threads hang almost all of the time, and are blocked in OpenMessageStore with one thread blocked in SubmitMessage.
As you can see from the existing test code in TestMAPI.cpp, SendTest opens the outbox and then sends the message so I wonder if there is some scenario that leads to a deadlock here?
The code below represents my changes FYI:
void main(int argc, char* argv[])
{
DWORD test_thread_ID = 0;
<pre>
BOOL flag;
flag = CMAPIEx::Init();
if(!flag)
{
PRINTF(_T("Failed to initialize MAPI.\n"));
return;
}
CreateThread(NULL, 0, &(ThreadEntryPoint), NULL, 0, &(test_thread_ID));
CreateThread(NULL, 0, &(ThreadEntryPoint), NULL, 0, &(test_thread_ID));
CreateThread(NULL, 0, &(ThreadEntryPoint), NULL, 0, &(test_thread_ID));
CreateThread(NULL, 0, &(ThreadEntryPoint), NULL, 0, &(test_thread_ID));
CreateThread(NULL, 0, &(ThreadEntryPoint), NULL, 0, &(test_thread_ID));
CreateThread(NULL, 0, &(ThreadEntryPoint), NULL, 0, &(test_thread_ID));
CreateThread(NULL, 0, &(ThreadEntryPoint), NULL, 0, &(test_thread_ID));
CreateThread(NULL, 0, &(ThreadEntryPoint), NULL, 0, &(test_thread_ID));
CreateThread(NULL, 0, &(ThreadEntryPoint), NULL, 0, &(test_thread_ID));
CreateThread(NULL, 0, &(ThreadEntryPoint), NULL, 0, &(test_thread_ID));
CreateThread(NULL, 0, &(ThreadEntryPoint), NULL, 0, &(test_thread_ID));
CreateThread(NULL, 0, &(ThreadEntryPoint), NULL, 0, &(test_thread_ID));
CreateThread(NULL, 0, &(ThreadEntryPoint), NULL, 0, &(test_thread_ID));
CreateThread(NULL, 0, &(ThreadEntryPoint), NULL, 0, &(test_thread_ID));
CreateThread(NULL, 0, &(ThreadEntryPoint), NULL, 0, &(test_thread_ID));
CreateThread(NULL, 0, &(ThreadEntryPoint), NULL, 0, &(test_thread_ID));
CreateThread(NULL, 0, &(ThreadEntryPoint), NULL, 0, &(test_thread_ID));
CreateThread(NULL, 0, &(ThreadEntryPoint), NULL, 0, &(test_thread_ID));
CreateThread(NULL, 0, &(ThreadEntryPoint), NULL, 0, &(test_thread_ID));
CreateThread(NULL, 0, &(ThreadEntryPoint), NULL, 0, &(test_thread_ID));
CreateThread(NULL, 0, &(ThreadEntryPoint), NULL, 0, &(test_thread_ID));
CreateThread(NULL, 0, &(ThreadEntryPoint), NULL, 0, &(test_thread_ID));
CreateThread(NULL, 0, &(ThreadEntryPoint), NULL, 0, &(test_thread_ID));
CreateThread(NULL, 0, &(ThreadEntryPoint), NULL, 0, &(test_thread_ID));
CreateThread(NULL, 0, &(ThreadEntryPoint), NULL, 0, &(test_thread_ID));
Sleep(-1);
CMAPIEx::Term();
}
DWORD WINAPI ThreadEntryPoint (void * arg)
{
char subject[64];
BOOL flag = FALSE;
for (int X=0; X < 5; X++)
{
CMAPIEx * mapi = new CMAPIEx();
flag = mapi->Login();
if (!flag)
{
PRINTF(_T("Failed to login to MAPI.\n"));
delete mapi;
return 1;
}
flag = mapi->OpenMessageStore();
if (!flag)
{
PRINTF(_T("Failed to open MAPI message store.\n"));
delete mapi;
return 1;
}
SendTest(*mapi);
}
return 0;
}
void SendTest(CMAPIEx& mapi)
{
if(mapi.OpenOutbox())
{
CMAPIMessage message;
if(message.Create(&mapi, IMPORTANCE_LOW))
{
message.SetSender(FROM_NAME, FROM_EMAIL);
message.SetSubject(_T("Subject"));
message.SetBody("Body");
message.AddRecipient(TO_EMAIL1);
message.AddRecipient(TO_EMAIL2);
message.AddRecipient(TO_EMAIL3);
message.AddAttachment(MSG_ATTACHMENT);
if(message.Send())
{
LONG cont = InterlockedIncrement(&send_counter);
PRINTF(_T("Sent successfully: %lu\n"), cont);
}
}
}
}
|