BUG: Registry Access from Multiple Threads Might Fail

Last reviewed: November 26, 1997
Article ID: Q176906
The information in this article applies to:
  • Microsoft Win32 Application Programming Interface (API) included with: - Microsoft Windows NT 4.0

SYMPTOMS

If you simultaneously access the same registry key from multiple threads in a single process, an error might occur. For example, if several threads in a carefully designed multi-threaded Win32 application try to open the same registry key using RegOpenKeyEx()in a loop, the function could fail with the following error code of 6:

   ERROR_INVALID_HANDLE

This error does not occur across process boundaries. Thus, two single- threaded processes that are competing for the same registry key will not be affected by this bug.

CAUSE

This behavior is intermittent and is the result of a race condition between the threads simultaneously accessing the same registry key.

RESOLUTION

There are several possible workarounds for this situation:

  1. Do not access the same registry location from multiple threads in a single process.

  2. Synchronize access to the registry location. You can do this by serializing access to the code that accesses the registry with a critical section or other Win32 synchronization mechanisms.

  3. When this error occurs, Sleep() a short time and try to access the registry key again. It is a race condition that causes this problem, so this workaround is not guaranteed to work. It is possible that the registry key is indeed invalid. However, this is the easiest solution to work into an existing application.

STATUS

Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article. We are researching this bug and will post new information here in the Microsoft Knowledge Base as it becomes available.

MORE INFORMATION

The following sample code illustrates the problem with the RegOpenKeyEx() function. Note that the error only happens intermittently with the following code.

Sample Code

   #include <windows.h>
   #include <winbase.h>
   #include <stdio.h>

   #define ITERATIONS 1000
   VOID ThreadFunc(LPVOID);

   void main(void)
   {
    int numThreads=100;
    DWORD threadID;
    int i;

     for (i=0; i<numThreads; i++)
     {
       CreateThread(0, 0,(LPTHREAD_START_ROUTINE) ThreadFunc,
                    0, 0, &threadID);
     }
     return;
   }

   VOID ThreadFunc(LPVOID)
   {
     LONG rc;
     HKEY hKey;

     for(int i=0; i < ITERATIONS; i++)
     {
       rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft",
                          0, KEY_ALL_ACCESS, &hKey);

       if (rc != ERROR_SUCCESS)
         printf("Iteration(%d): Thread Id: %d, Error=%d\r\n", i,
                                   GetCurrentThreadId(), rc);
       else
          rc = RegCloseKey(hKey);
     }
   }


Additional query words: regedit problem known occasionally concurrently
RegOpenKey RegCloseKey
Keywords : BseRegistry kberrmsg
Version : WINNT:4.0
Platform : winnt
Issue type : kbbug


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: November 26, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.