php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #45894 PHP (cleanup?) runs infinite loop after ODBC used
Submitted: 2008-08-22 20:09 UTC Modified: 2020-10-05 08:06 UTC
Votes:2
Avg. Score:4.5 ± 0.5
Reproduced:2 of 2 (100.0%)
Same Version:1 (50.0%)
Same OS:0 (0.0%)
From: ashoat at gmail dot com Assigned: cmb (profile)
Status: Closed Package: ODBC related
PHP Version: 5.2.6 OS: CentOS 5.2 x64_86
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: ashoat at gmail dot com
New email:
PHP Version: OS:

 

 [2008-08-22 20:09 UTC] ashoat at gmail dot com
Description:
------------
I have PHP 5.2.6 compiled as CGI wrapped with suPHP installed on a CentOS 5.2 x64_86 box. I compiled PHP with --with-unixODBC, version 2.2.11. 

After I open an ODBC connection and then close it, I am able to continue executing PHP code. However, when it is time to cleanup and exit the script, the parser stalls and does not close the stream.

This has been tested through the commandline and httpd. When I force close the command-line executor after the cleanup stalls, I get "Segmentation fault" appended to the end of the stream before it closes.

Reproduce code:
---------------
<?php
$connection = odbc_connect("DRIVER={MySQL ODBC 3.51 Driver};Server=localhost;Database=database;Option=3","username","password");
odbc_close($connection);

for($i=0;$i<25;$i++) echo "This is <b>after</b> the connection is closed.<br/>";
echo "Something is clearly wrong with PHP's cleanup.";

?>

Expected result:
----------------
The expected result is that the code executes and the stream then closes.

If the ODBC functions caused a block and did not close, a timeout would be expected and the code towards the end of the file would not execute. However, the code at the end does execute (see here: http://www.heliohost.org/test.php). 

Therefore, it seems that the issue here is with PHP's cleanup methods.

Actual result:
--------------
See here: http://www.heliohost.org/test.php

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2008-08-22 21:55 UTC] felipe@php.net
Thank you for this bug report. To properly diagnose the problem, we
need a backtrace to see what is happening behind the scenes. To
find out how to generate a backtrace, please read
http://bugs.php.net/bugs-generating-backtrace.php for *NIX and
http://bugs.php.net/bugs-generating-backtrace-win32.php for Win32

Once you have generated a backtrace, please submit it to this bug
report and change the status back to "Open". Thank you for helping
us make PHP better.


 [2008-08-22 23:19 UTC] ashoat at gmail dot com
Attached is the backtrace. Note that the segfault is not generated unless a force-close the command-line php interpreter by hitting Ctrl+C.

(gdb) bt
#0  0x000000308dab93d0 in ?? ()
#1  <signal handler called>
#2  0x0000003a2c80c898 in __lll_mutex_lock_wait () from /lib64/libpthread.so.0
#3  0x0000003a2c80a315 in _L_mutex_lock_18 () from /lib64/libpthread.so.0
#4  0x0000003a2c80a273 in pthread_cond_destroy@@GLIBC_2.3.2 ()
   from /lib64/libpthread.so.0
#5  0x0000003a340269fb in my_thread_global_end () at my_thr_init.c:216
#6  0x0000003a34022265 in my_end (infoflag=0) at my_init.c:205
#7  0x0000003a3402100f in mysql_server_end () at libmysql.c:197
#8  0x000000000061f546 in zm_shutdown_mysql (type=1, module_number=21,
    tsrm_ls=0x192909c0)
    at /home/cpeasyapache/src/php-5.2.6/ext/mysql/php_mysql.c:426
#9  0x00000000008879fc in module_destructor (module=0x193015e0)
    at /home/cpeasyapache/src/php-5.2.6/Zend/zend_API.c:1921
#10 0x000000000088df4b in zend_hash_apply_deleter (ht=0xf37700, p=0x19301580)
    at /home/cpeasyapache/src/php-5.2.6/Zend/zend_hash.c:611
#11 0x000000000088e0b7 in zend_hash_graceful_reverse_destroy (ht=0xf37700)
    at /home/cpeasyapache/src/php-5.2.6/Zend/zend_hash.c:646
#12 0x000000000087cea7 in zend_shutdown (tsrm_ls=0x192909c0)
    at /home/cpeasyapache/src/php-5.2.6/Zend/zend.c:733
#13 0x000000000080476f in php_module_shutdown (tsrm_ls=0x192909c0)
    at /home/cpeasyapache/src/php-5.2.6/main/main.c:1888
#14 0x000000000091a396 in main (argc=2, argv=0x7ffff8753f88)
 [2008-08-24 07:26 UTC] ashoat at gmail dot com
I've experimented around, and I have a few updates:
1) This problem is not general to all ODBC drivers. When I attempt a connection to PostgreSQL (I have PostgreSQL/psqlodbc installed as well as MySQL/Connector ODBC), I experience no problems.
2) This problem is not specific to MySQL/Connector ODBC. When I attempt an ODBC connection from ASP.NET (Mono Project v1.9.1), there is no stalling in the connection or cleanup.

For the record, I am using unixODBC 2.2.11 and MySQL Connector/ODBC 3.51.26.

The above points lead me to the conclusion that this is an issue with PHP's behavior when it is passed a certain parameter by ODBC that coincedentally is passed by MySQL/Connector ODBC. This conclusion seems to be supported by the backtrace, although I am confused as to the jump between frame #8 and frame #9. 

More information from gdb on those frames:
(gdb) frame 9
#9  0x00000000008879fc in module_destructor (module=0x193015e0)
    at /home/cpeasyapache/src/php-5.2.6/Zend/zend_API.c:1921
1921                    module->module_shutdown_func(module->type, module->module_number TSRMLS_CC);
(gdb) frame 8
#8  0x000000000061f546 in zm_shutdown_mysql (type=1, module_number=21,
    tsrm_ls=0x192909c0)
    at /home/cpeasyapache/src/php-5.2.6/ext/mysql/php_mysql.c:426
426             mysql_server_end();

Forgive me if I am wrong here, but I am baffled as to why PHP is calling ext/mysql/php_mysql.c. At no point is the MySQL extension used - I am exclusively using the ODBC (Unified) extension. Furthermore, if PHP was indeed utilizing the ODBC extension then wouldn't libodbc appear as an intermediary somewhere in the stack?

If I were asked to guess what the issue was here, I would think that somewhere in the PHP source there is a filter to catch all calls for Driver={MySQL ODBC} in odbc_connect() and to channel them to the MySQL extension. Of course, I have never even looked at the PHP source, so I may be totally wrong :)

Whatever the problem is, such behavior should not be happening and I would strongly discourage anybody on the team from pinning the blame on unixODBC or MySQL Connector/ODBC. Whatever the issue is, PHP should always successfully close a stream and if there is an issue on either of the above module's sides then an appropriate error message should be given.

Thanks a lot for taking the time from your busy schedules to investigate this bug! Myself and others appreciate your open-source and collaborative effort to keep the PHP project up and running.
 [2008-08-25 07:41 UTC] ashoat at gmail dot com
OK, after examining PHP's source code a bit, it seems that the issue here is that when the ODBC extension is cleaning up its connection with MySQL, it interferes with the MySQL's extension's cleanup.

As a result, MySQL blocks at some later point when trying to kill some MySQL thread.

You can disregard most of my last post, except the two points listed at the top.
 [2020-10-05 08:06 UTC] cmb@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: cmb
 [2020-10-05 08:06 UTC] cmb@php.net
> […], it seems that the issue here is that when the ODBC
> extension is cleaning up its connection with MySQL, it interferes
> with the MySQL's extension's cleanup.

Indeed, but since the mysql extension is long gone, I think this
ticket can be closed.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 25 22:01:29 2024 UTC