Microsoft Knowledge Base Email Alertz

(294140) - When an application that uses multiple threads that share a global environment handle implements Open Database Connectivity (ODBC) connection pooling, the application may stop responding (hang) on the platforms listed above with MDAC version 2.5 or...

Search KbAlertz

Advanced Search

Receive Microsoft Knowledge Base articles by E-Mail?

Every night we scan the Microsoft Knowledge Base. If technologies you're interested in are updated, we'll send you an e-mail. You only get one e-mail a day, and only when new articles are added.

Click here to create a
FREE account
Already have an account?
[Click here to Login]











Microsoft Knowledge Base Article

This article contents is Microsoft Copyrighted material.
©2005-©2007 Microsoft Corporation. All rights reserved. Terms of Use | Trademarks

Article ID: 294140 - Last Review: December 21, 2004 - Revision: 4.0

FIX: Connection pooling causes Windows 2000 computer with MDAC 25/2.5 SP1 to stop responding

This article was previously published under Q294140

On This Page

SYMPTOMS

When an application that uses multiple threads that share a global environment handle implements Open Database Connectivity (ODBC) connection pooling, the application may stop responding (hang) on the platforms listed above with MDAC version 2.5 or MDAC verion 2.5 Service Pack 1.

CAUSE

This problem is due to a bug in the Mtxdm.dll file that ships with MDAC 2.5 and 2.5 SP1.

STATUS

This problem was corrected in MDAC version 2.6.

MORE INFORMATION

This problem occurs regardless of the ODBC driver you are using and the datasource you are going against.

Steps to reproduce behavior

  1. Create a new Visual C++ Console application and paste the following code into a .cpp file:
    
    #include <iostream.h>
    #include <windows.h>
    #include <SQL.h>
    #include <SQLEXT.h>
    #include <ODBCINST.h>
    #include <stdio.h>
    #include <process.h>
    #define MAXBUFLEN 255
    
    unsigned __stdcall TestPooling(LPVOID pParam);
    void	ProcessLogMessages(SQLSMALLINT plm_handle_type,
    						   SQLHANDLE plm_handle, char *logstring);
    HENV g_henv;
    
    
    
    DWORD g_dwIterations = 10;
    DWORD g_dwWorkerThreads = 2;
    
    int main(int argc, char **argv)
    {
            DWORD mydata;
            SQLRETURN nSQLRetCode = SQLSetEnvAttr(SQL_NULL_HENV,  SQL_ATTR_CONNECTION_POOLING, (void*)SQL_CP_ONE_PER_DRIVER, 0);
    	
    	nSQLRetCode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HENV, &g_henv);
    	
    	nSQLRetCode = SQLSetEnvAttr(g_henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);
    	
    		
    	cout	<< "Enter number of worker threads:";
    	cin		>> g_dwWorkerThreads;
    
    	cout	<< "Enter no of iterations:";
    	cin		>> g_dwIterations;
    
    	int nDelay = 0;
    	cout	<< "Delay:";
    	cin		>> nDelay;
    
    	HANDLE *pThreadHandles = new HANDLE[g_dwWorkerThreads];
    
    	unsigned int dwThreadId = 0;
    	for ( DWORD i = 0; i < g_dwWorkerThreads; i++)
    	{
    		pThreadHandles[i] = (HANDLE)_beginthreadex(NULL,0,TestPooling, NULL, 0, &dwThreadId );
    		printf("Creating thread<%d><%d>\n", i, dwThreadId);
    		
    		if ( nDelay > 0 )
    		{
    			Sleep(nDelay); 
    		}
    	
    	}
    	
    	printf("Waiting for worker threads to finish\n");
    
    	
    	mydata= WaitForMultipleObjects(g_dwWorkerThreads,pThreadHandles,TRUE,INFINITE);
    
    	printf("Done waiting for worker threads to finish!\n");
    	getchar();
    
        return (0);
    }
    
    unsigned __stdcall TestPooling(LPVOID pParam)
    {
    	SQLRETURN nSQLRetCode = SQL_SUCCESS;
    
    	SQLHDBC		m_hdbc;
    	char buffer[256];
    	
    	TCHAR tConnectionStringIn[ 256 ], tConnStringOut[256];
    	SWORD	cLength = 0;	SDWORD	cbTemp = 0;	SQLRETURN nRetCode =SQL_SUCCESS;
    
    	for ( DWORD i = 0; i < g_dwIterations; i++ )
    	{
    		do
    		{
    			nSQLRetCode = SQLAllocHandle(SQL_HANDLE_DBC, g_henv, &m_hdbc);
    			if ( SQL_ERROR == nSQLRetCode )
    			{
    				printf("Allocating connection handle failed");
    				break;
    			}
    	
    			sprintf(	tConnectionStringIn,  
    						"DRIVER={SQL Server};SERVER=%s;UID=%s;PWD=%s;DATABASE=%s;APP=%s",
    						"TestMSSQLServer", "sa","","pubs","pooltest");
    		         sprintf(buffer,"This is thread 0x%08x. before SQLDriverconnect .\n",GetCurrentThreadId());
    			OutputDebugString(buffer);
    
    			
    			nSQLRetCode = SQLDriverConnect(m_hdbc, NULL, (SQLTCHAR*) tConnectionStringIn,strlen( tConnectionStringIn ),
                                                          (SQLTCHAR*) tConnStringOut,(SWORD)(sizeof(tConnStringOut)/sizeof(TCHAR)),
                                                          &cLength, SQL_DRIVER_NOPROMPT);	//connect to the odbc
    			
    		         if (nSQLRetCode == SQL_ERROR)
    		         {
    	   	            ProcessLogMessages(SQL_HANDLE_DBC, m_hdbc, "SQLConnect() Failed\n\n");
    	   	           break;
    		         }
    	
    
    			sprintf(buffer,"This is thread 0x%08x.after  SQLDriverConnect \n",GetCurrentThreadId());
    		         OutputDebugString(buffer);
    
    
    			SQLDisconnect(m_hdbc);	
    			sprintf(buffer,"This is thread 0x%08x.after SQLDisconnect\n",GetCurrentThreadId());
           		         OutputDebugString(buffer);
    
    			SQLFreeHandle(SQL_HANDLE_DBC, m_hdbc);	
    			sprintf(buffer,"This is thread 0x%08x. after SQLFreeHandle dbc\n",GetCurrentThreadId());
    			OutputDebugString(buffer);   
    	
    		} while ( FALSE );
    	}
    
    	printf("<%d>Done\n",GetCurrentThreadId());
    
    	return 100;
    }
    
    void ProcessLogMessages(SQLSMALLINT plm_handle_type, SQLHANDLE plm_handle,
    						char *logstring)
    {
    	RETCODE		plm_retcode = SQL_SUCCESS;
    	UCHAR		plm_szSqlState[MAXBUFLEN] = "",plm_szErrorMsg[MAXBUFLEN] = "";
    	SDWORD		plm_pfNativeError = 0L;
    	SWORD		plm_pcbErrorMsg = 0;
    	SQLSMALLINT	plm_cRecNmbr = 1;
    
    	printf(logstring);	
    
    	while (plm_retcode != SQL_NO_DATA_FOUND)
    	{
    		plm_retcode = SQLGetDiagRec(plm_handle_type, plm_handle,
    			plm_cRecNmbr, plm_szSqlState, &plm_pfNativeError,
    			plm_szErrorMsg, MAXBUFLEN - 1, &plm_pcbErrorMsg);
    		if (plm_retcode != SQL_NO_DATA_FOUND)
    		{
    			printf("szSqlState = %s\n",plm_szSqlState);
    			printf("pfNativeError = %d\n",plm_pfNativeError);
    			printf("szErrorMsg = %s\n",plm_szErrorMsg);
    			printf("pcbErrorMsg = %d\n\n",plm_pcbErrorMsg);
    		}
    		plm_cRecNmbr++;
    	} // end while
    }
    					
  2. Compile and run the project.

REFERENCES

For additional information on ODBC connection pooling, click the following article numbers to view the articles in the Microsoft Knowledge Base:
164221  (http://kbalertz.com/Feedback.aspx?kbNumber=164221/ ) How to enable connection pooling in an ODBC application
161634  (http://kbalertz.com/Feedback.aspx?kbNumber=161634/ ) Connection pooling requires same henv and driver
216950  (http://kbalertz.com/Feedback.aspx?kbNumber=216950/ ) How to enable ODBC connection pooling performance counters

APPLIES TO
  • Microsoft Data Access Components 2.5, when used with:
    • Microsoft Windows 2000 Advanced Server
    • Microsoft Windows 2000 Service Pack 1
    • Microsoft Windows 2000 Service Pack 1
  • Microsoft Data Access Components 2.5 Service Pack 1, when used with:
    • Microsoft Windows 2000 Advanced Server
    • Microsoft Windows 2000 Service Pack 1
    • Microsoft Windows 2000 Service Pack 1
Keywords: 
kbbug kbfix kbmdac260fix KB294140
       

Community Feedback System

Very often, it takes hours to solve a problem. Very often, you've looked high and low, and have tried a lot of solutions. When you finally found it, chances are, it was because someone else helped you. Here's your chance to give back. Use our community feedback tool to let others know what worked for you and what didn't.

Please also understand that the community feedback system is not warranted to be correct, it's simply a system that we've built to let people try and help each other. If something in a feedback response doesn't make sense to you, or you're not comfortable making changes that the feedback talks about (like registry edits), please consult a professional.

Thank you for using kbAlertz.com Feedback System.

-- Scott Cate