ID: 24463 User updated by: nospam at kolbly dot com Reported By: nospam at kolbly dot com Status: Open -Bug Type: Feature/Change Request +Bug Type: IIS related Operating System: Win2003 Server PHP Version: 4.3.2 New Comment:
An update and some additional comments : I have been able to suck out odbc calls from the php source php_odbc.c and been able to recreate the problem using code I'll post to the end of this message. I've successfully opened up a case w/Microsoft and they're in the process of recreating the problem in their labs. I'll post their results here. One note : php_odbc.c has many calls that are deprecated by Microsoft. This may or may not be a contributing factor. I've been able to successfully eliminate the problem on my test platform by adding a Sleep(1) at the end of each of the following functions in php_odbc.c - SQLFreeStmt(), SQLDisconnect(), SQLFreeConnect(), and SQLFreeEnv(). Unrelated side note to PHP developers: When PHP is compiled with Cygwin utils instead of the win32build\bin utils, then php.ini ALWAYS has a parsing problem at the last line. An update to the windows install doc would likely save many a developer some frustration. breakiis.c ..... #include <windows.h> #include <sql.h> #include <sqlext.h> #include <stdlib.h> #include <time.h> #include <stdio.h> #define MYSQLSUCCESS(rc) ((rc==SQL_SUCCESS)||(rc==SQL_SUCCESS_WITH_INFO)) #define MAX_NAMES 100 #define MAX_NAME_SIZE 25 #define DSN "bug" // ODBC System Data Source, points to Northwind DB #define DB_USER "buguser" // Database user with privileges on Northwind DB #define DB_PASS "bugpass" // Database password #define LOGFILE "d:\\weblogs\\mydebug.log" void single_page_load(); void auto_reload_page(); void get_data_using_odbc(int *count, char names[][MAX_NAME_SIZE]); void mydebug(const char *msg); /** **************************************************************************** * main() * * Try to break IIS using native ODBC funcs **************************************************************************** */ int main(int argc, char* argv[]) { mydebug("main() start..."); auto_reload_page(); mydebug("main() end..."); return 0; } /** **************************************************************************** * get_data_using_odbc() * * Connect to the SQL Server 2000 Database Northwind * Setup an ODBC DataSource named DSN, a Database user DB_USER, and * password DB_PASS. **************************************************************************** */ void get_data_using_odbc(int *count, char names[][MAX_NAME_SIZE]) { RETCODE rc; // ODBC return code HENV henv; // Environment HDBC hdbc; // Connection handle HSTMT hstmt; // Statement handle unsigned char szData[100]; // Returned data storage SDWORD cbData; // Output length of data int index = 0; DWORD zzz = 1; // Sleep period - Set to 1 to aleviate problem mydebug("get_data_using_odbc() start..."); // Connect Up SQLAllocEnv(&henv); SQLAllocConnect(henv,&hdbc); rc = SQLConnect(hdbc, (SQLCHAR *)DSN, SQL_NTS, (SQLCHAR *)DB_USER, SQL_NTS, (SQLCHAR *)DB_PASS, SQL_NTS); // Exec Stmt rc = SQLAllocStmt(hdbc,&hstmt); rc = SQLExecDirect(hstmt, (SQLCHAR *)"SELECT FirstName FROM employees", SQL_NTS); for (rc = SQLFetch(hstmt); (rc == SQL_SUCCESS) && (index < MAX_NAMES); rc=SQLFetch(hstmt)) { SQLGetData(hstmt, 1, SQL_C_CHAR, szData, sizeof(szData), &cbData); sprintf(names[index], "%s", (const char *) szData); index++; } *count = index; SQLFreeStmt(hstmt, SQL_DROP); //Sleep(zzz); rc = SQLDisconnect(hdbc); //Sleep(zzz); rc = SQLFreeConnect(hdbc); //Sleep(zzz); rc = SQLFreeEnv(henv); //Sleep(zzz); mydebug("get_data_using_odbc() end..."); }// get_data_using_odbc() /** **************************************************************************** * auto_reload_page() * * Have the web page keep reloading itself while incrementing a counter **************************************************************************** */ void auto_reload_page() { char *data; double count; int i; char names[MAX_NAMES][MAX_NAME_SIZE]; int num = 0; mydebug("auto_reload_page() start..."); ZeroMemory(names, sizeof(names)); // Comment out below and this page reloads just fine get_data_using_odbc(&num, names); data = getenv("QUERY_STRING"); if(data == NULL) count=1; else count = atof(data); printf("content-type: text/html\n\n"); printf("<html>"); printf("<head>"); printf("<title>BreakIIS</title>"); printf("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">"); printf("</head>"); printf("<body>"); printf("Loading page with value %5f<br><br>\n", count); count++; for (i = 0; i < num; i++) { printf("%s<br>\n", names[i]); } printf("<script>location.href='breakiis.exe?%f'</script>", count); printf("</body>"); printf("</html>"); mydebug("auto_reload_page() end..."); }// auto_reload_page() /** **************************************************************************** * void single_page_load() * * Have the web page keep reloading itself once the user presses "submit" **************************************************************************** */ void single_page_load() { int i; char names[MAX_NAMES][MAX_NAME_SIZE]; int num = 0; ZeroMemory(names, sizeof(names)); get_data_using_odbc(&num, names); printf("content-type: text/html\n\n"); printf("<html>"); printf("<head>"); printf("<title>BreakIIS</title>"); printf("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">"); printf("</head>"); printf("<body>"); for (i = 0; i < num; i++) { printf("%s<br>\n", names[i]); } printf("<form name=\"form1\" method=\"post\" action=\"breakiis.exe\">"); printf("<p>Click Submit to post back to this page.</p>"); printf("<input type=\"submit\" name=\"Submit\" value=\"Submit\">"); printf("</form>"); printf("</body>"); printf("</html>"); }// single_page_load() /** **************************************************************************** * mydebug() * * Simply write a logfile to LOGFILE **************************************************************************** */ void mydebug(const char *msg) { char datetime[120]; FILE *f; time_t curtime; struct tm *loctime; ZeroMemory(datetime, sizeof(datetime)); curtime = time(NULL); loctime = localtime(&curtime); strftime(datetime, 119, "%Y-%m-%d %H:%M:%S", loctime); f = fopen(LOGFILE, "a"); if (f) { fprintf(f, "%s : %s\n", datetime, msg); fclose(f); } }// mydebug() Previous Comments: ------------------------------------------------------------------------ [2003-07-02 13:19:35] nospam at kolbly dot com Description: ------------ When redirecting to a .php page that connects to an SQL Server database via ODBC, IIS produces a 502 error intermittently on slower machines and 100% on faster machines. This is admittedly a duplicate of Bug #9852 (Which is currently closed), but my tests have pointed that the problem is with PHP, not IIS. I have opened up an Incident with Microsoft and we are at the point where if I can reproduce the bug using some non-php code, they will duplicate my setup exactly in their lab and have their developers tackle it. But, so far I cannot reproduce the error with any non-php code. I traced the php function calls, and wrote a C program that calls the exact same odbc calls as php, but this does NOT break IIS. I can only conclude that the issue is within PHP or Zend or at the very least it is still very much in doubt as to which code is at fault here. I have tried ALL the suggested workarounds from Bug #9852 with no luck. I will be forced to rewrite 8 websites in .asp or .net if I can’t fix this. If anybody has a way to reproduce this error using C/C++/C#/ASP or some other “Microsoft-Approved” language, please send me your source code. ([EMAIL PROTECTED]) Reproduce code: --------------- <?php $dbconn = odbc_connect("bug", "buguser", "bugpass"); $rs = odbc_exec($dbconn, "select * from employees"); while(odbc_fetch_row($rs)) { $EmployeeID = odbc_result($rs, "EmployeeID"); } if (isset($_POST['Submit'])) { header("Location: test1a.php"); die; } ?> <html> <head> <title>Bug Test</title> <meta http-equiv="Content-Type" content="text/plain; charset=iso-8859-1"> </head> <body> <form name="form1" method="post" action="test1a.php"> <p>Click Submit to post back to this page.</p> <input type="submit" name="Submit" value="Submit"> </form> </body> </html> Expected result: ---------------- Click Submit to post back to this page. [Submit] Actual result: -------------- CGI Error The specified CGI application misbehaved by not returning a complete set of HTTP headers. ------------------------------------------------------------------------ -- Edit this bug report at http://bugs.php.net/?id=24463&edit=1