|
 |
 |
 |
 |
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 respondingThis article was previously published under Q294140
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.
This problem is due to a bug in the Mtxdm.dll file that ships with MDAC 2.5 and 2.5 SP1.
This problem was corrected in MDAC version 2.6.
This problem occurs regardless of the ODBC driver you are using and the datasource you are going against.
Steps to reproduce behavior- 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
}
- Compile and run the project.
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
| 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
|
 |
 |
 |
 |
 |
 |
 |
| |