Do You Feel Lucky? Multithreading the Profile API


I picked up a case a few weeks ago that had a simple question in it. “Are MAPI’s profile APIs thread safe?” My answer, of course, was “As far as I know – why do you ask?”. The reason they asked was because they had built a framework to encapsulate all of their MAPI operations (a very good idea) and they were seeing “issues” when they ran the profile configuration portion of that framework through their multithreaded test harness.

At first, I had a little trouble pinning down what they meant by “issues” – did they mean hangs? Crashes? Random error codes? Actually – it was all of the above. I got some dumps and traces from them and found 2-3 distinct problems with the way MAPI and some of the providers behave in an non thread safe manner during profile configuration/deletion. When I started running my own tests, I found a few more.

Now – I’ve always understood MAPI and the providers we ship to be thread safe. Sure, there are the occasional issues, but we usually can fix them. We go to a lot of trouble to make sure MAPI behaves correctly across multiple threads. But apparently all of this work, and all of our testing, was under the assumption that the profiles had already been created. I dug back through records of cases I had worked as well as bugs which have been filed against MAPI and found only one case where someone had configured profiles from multiple threads. And on examining that case, I saw that it was from the days before we routinely had multiple processors. Most of the threading issues I was seeing would be much harder to reproduce on a single processor.

I took the list of issues we found back to development to see what they thought we should do about this. The issues we found were in both Outlook and Exchange’s implementation of MAPI (they predate the split), meaning we had a long road ahead of us if we started fixing the problems. And even if we assume we fixed every issue we found, we were certain to find that those issues were hiding other, nastier issues.

So we decided that the best course of action here would be to declare MAPI’s profile API’s not to be thread safe. All MAPI profile configuration should be serialized. This applies to both Exchange and Outlook’s implementations of MAPI and all versions, including the MAPI download.

Here are the APIs you’ll need to serialize as a MAPI client:

Comments (9)

  1. john g says:

    We’re using the MAPI API to create msg files from a C# web service; and we’re using redemption to access MAPI without raising the security warnings.  It runs fine for a long time but then randomly fails. Could this be the threading issue that you describe above?  We’ve rebuild the account profile which fixed the problem the last time it occured. Any advice will be much appreciated.

  2. Doubtful. But you should take Redemption issues to the maker of Redemption.

  3. Torbjorn Jansson says:

    is it also unsafe to use the profile api from multiple exe files at the same time?

    what i have is a program that do the mapi work as a separate process and not threads.

    that program begins with creating a temporary profile and onced its finished it cleans up the profile after itself.

  4. As far as I remember, the threading problems were within a process. Multiple processes are probably fine.

  5. Vladimir Werskov says:

    Any chance to know more about these problems? Exactly which methods of these interfaces should be serialized? If we need to serialize all those profile creation parts, then it is a rather nasty performance hit.

    Do i need to serialize also the call to ConfigureMsgService?

  6. >Exactly which methods of these interfaces should be serialized?

    All of them. But I wouldn’t serialize them individually. I’d serialize the whole act of profile creation/modification.

    >If we need to serialize all those profile creation parts, then it is a rather nasty performance hit.

    Doubtful – profile creation should only need to be done occasionally (like when you install, or maybe during app startup), so serializing it wouldn’t have any measurable performance hit.

  7. Vladimir Werskov says:

    Just imagine a scenario where you can’t keep the profiles – you have many mailboxes and for each one you need more threads. This can be a very high number. Without cleaning up the profiles you end up with full registry – which can turn to be irreparable.

    What is my concern: imagine that you need to create a profile for a mailbox, which is not available (network error, etc) – when configuring such a profile, you need to wait until it returns after a timeout. During this time (assuming you have serialized the profile actions) everybody is locked out and is not able to create a profile when it is needed. And that timeout can be really nasty (some minutes or so). How to overcome this case? Start a process to create a profile for you?

  8. If you’re creating that many profiles, you’re doing it wrong. You should look at CreateStoreEntryID (which *is* thread safe – all it does is bit twiddling).

    I’m not dismissing your concerns, but concocting scenarios won’t make these interfaces thread safe. Any calls into them need to be serialized.

  9. Hi Stephen,
    Greetings.
    I am working on a requirement where we need to import e-mails in MSG format in PSTs. I have written a tool in C++ and used MAPI API to import MSG files in PSTs. The tool consists of a .dll that uses different MAPI APIs to read MSG file and import it into a PST and a .exe that passes MSG filename and PST filename to .dll. We need to invoke .exe thousands of time to import thousands of MSG files into PSTs. I am observing following things with outlook 2010 :-

    1) When we are running single .exe repeatedly thousand of times by passing different MSG filenames and PST filenames each time, it works well without any error.
    2) When we are running multiple .exes simultaneously (thousand of times) by passing different MSG filenames and PST filenames each time, I am seeing random MAPI API failues as follows:-

    m_pIProfAdmin->CreateProfile() failed :: -2147024891 (MAPI_E_NO_ACCESS)
    MAPILogonEx failed :: -2147221231 (MAPI_E_LOGON_FAILED)
    m_pSvcAdmin->CreateMsgService() failed :: -2147467259 (MAPI_E_CALL_FAILED)
    OpenMsgStore() failed :: -2147221226 (MAPI_E_DISK_ERROR)

    Such failures are random in nature and about 5 transactions out of 800 are showing such failures. In single process mode run, I never saw any failure at all. I also tried putting inter-process locks around MAPI API calls so that they become serial in nature, still I am getting these errors when I am invoking multiple .exes simultaneously.

    Are you aware of any known issue related to multi-process invocation of MAPI API related to profile management? How to address such failures in multi-process execution?

    Your inputs will help me to proceed ahead with my implementation.

    Thanks in advance,
    Yashpal

    Hi Stephen,
    Greetings!!
    I am working on a requirement where we need to import e-mails in MSG format into PST files. I have written a tool in C++ and used MAPI API to import MSG files into PSTs. The tool consists of a .dll that uses different MAPI APIs to read MSG file and import it into a PST and a .exe that passes MSG filename and PST filename to the .dll. We need to invoke .exe thousands of time to import thousands of MSG files into PSTs.

    I am observing following behaviour in my testing with outlook 2010:-

    1) When we are running single .exe repeatedly thousand of times by passing different MSG filenames and PST filenames each time, it works well without any error.
    2) When we are running multiple .exes simultaneously (thousand of times) by passing different MSG filenames and PST filenames each time, I am seeing random MAPI API failues as follows:-

    m_pIProfAdmin->CreateProfile() failed :: -2147024891 (MAPI_E_NO_ACCESS)
    MAPILogonEx failed :: -2147221231 (MAPI_E_LOGON_FAILED)
    m_pSvcAdmin->CreateMsgService() failed :: -2147467259 (MAPI_E_CALL_FAILED)
    OpenMsgStore() failed :: -2147221226 (MAPI_E_DISK_ERROR)

    Such failures are random in nature and about 10 transactions out of 500 are showing such failures.
    In single process mode run, I never saw any failure at all. I also tried putting inter-process locks around MAPI API calls so that they become serial in nature, still I am getting these errors when I am invoking multiple .exes simultaneously.

    Are you aware of any known issue related to multi-process invocation of MAPI API related to profile management? How to address such failures in multi-process execution?

    Your inputs will help me to proceed ahead with my implementation.

    Thanks in advance,
    Yashpal

Skip to main content