php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #72175 Impossibility of creating multiple connections to Interbase with php 7.x
Submitted: 2016-05-09 07:23 UTC Modified: 2019-03-25 15:48 UTC
Votes:38
Avg. Score:4.7 ± 0.6
Reproduced:34 of 35 (97.1%)
Same Version:21 (61.8%)
Same OS:12 (35.3%)
From: netvicious at gmail dot com Assigned: nikic (profile)
Status: Closed Package: InterBase related
PHP Version: 7.x OS: Ubuntu 16.04 LTS
Private report: No CVE-ID: None
 [2016-05-09 07:23 UTC] netvicious at gmail dot com
Description:
------------
If you have one open link to an Interbase/Firebird database and you open **another** one to the same database the first link it's closed.

On my php.ini I have this (exactly the same than on PHP 5.6):

    ibase.allow_persistent = 1

    ; Maximum number of persistent links. -1 means no limit.
    ibase.max_persistent = -1

    ; Maximum number of links (persistent + non-persistent). -1 means no limit.
    ibase.max_links = -1

The same script below was running perfectly on PHP 5.6

NikiC on StackOverflow writed this:
In particular, I don't think this line is correct: lxr.php.net/xref/PHP_MASTER/ext/interbase/interbase.c#943 This zend_list_close should probably be a zend_list_delete, otherwise it will simply always destroy the resource.

Already posted to:
http://stackoverflow.com/questions/37049534/multiple-connections-to-interbase-with-php-7-0
https://bugs.launchpad.net/ubuntu/+source/php7.0/+bug/1578600

Regards,

Test script:
---------------
// DB_xxx are defined variables with the users, password, ..... of the database.

// We have the same problem if we use ibase_pconnect or ibase_connect

$conx = ibase_connect(DB_HOST . ":" . DB_NAME,DB_USER,DB_PWD,DB_CHARACTER) or die(ibase_errcode() . ' ' . ibase_errmsg()); 

$conx2 = ibase_connect(DB_HOST . ":" . DB_NAME,DB_USER,DB_PWD,DB_CHARACTER) or die(ibase_errcode() . ' ' . ibase_errmsg()); 

$sql = 'SELECT something from somewhere';

$query = ibase_query($conx, $sql);

while ($row = ibase_fetch_assoc($query)) {
    echo $row['something'];
}

Expected result:
----------------
$conx should keep the database connection instead of be closed.

Actual result:
--------------
The test script should not write nothing, but on the error log you will see something like:

supplied resource is not a valid Firebird/InterBase link resource in ....

    ibase_fetch_assoc(): Dynamic SQL Error SQL error code = -504 Invalid cursor reference Cursor is not open ....

It seems $conx has been closed when creating the $conx2 connection.

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-05-26 15:45 UTC] dregad at mantisbt dot org
A user of ADOdb library reported the same problem (see https://github.com/ADOdb/ADOdb/issues/231).
 [2016-06-28 15:35 UTC] nish dot aravamudan at canonical dot com
As part of https://bugs.launchpad.net/ubuntu/+source/php7.0/+bug/1578600, I asked users to test:

--- php7.0-7.0.8.orig/ext/interbase/interbase.c
+++ php7.0-7.0.8/ext/interbase/interbase.c
@@ -939,7 +939,7 @@ static void _php_ibase_connect(INTERNAL_
                xlink = (zend_resource*) le->ptr;
                if ((!persistent && xlink->type == le_link) || xlink->type == le_plink) {
                        if (IBG(default_link)) {
-                               zend_list_close(IBG(default_link));
+                               zend_list_delete(IBG(default_link));
                        }
                        xlink->gc.refcount++;
                        xlink->gc.refcount++;

And two users reported this fixed the issue for them. This was the suggestion of NikiC on SO (http://stackoverflow.com/questions/37049534/multiple-connections-to-interbase-with-php-7-0).
 [2016-07-06 23:41 UTC] nikic@php.net
-Assigned To: +Assigned To: nikic
 [2016-07-08 15:57 UTC] nikic@php.net
I've tried applying the patch today (as well as interchanging the order of the recount increments) -- which does fix this issue, but also makes many ext/interbase tests fail.

The problem seems to be additional warnings like this:

Warning: ibase_drop_db(): lock time-out on wait transaction object /tmp/php_ibase_testhj4JRc is in use

I know nothing about interbase, so not sure what this is supposed to mean. My guess is that interbase is finicky about getting all connections closed and using delete() instead of close() here leaves connections open.
 [2016-07-10 11:44 UTC] nikic@php.net
The resource refcount management in ext/interbase is in general very broken. It uses zend_list_delete() in *_close() functions, which is not memory safe, and adds additional refs elsewhere to compensate.

I'm not even clear on how some parts of this are *supposed* to work. For example, what should this code do?

    $link = ibase_connect($foo);
    $link2 = ibase_connect($foo);
    ibase_close($link2);

Should this ibase_close() call close all of $link, $link2 and the default link? After all, all of these share the same connection. If ibase_close($link2) should not close $link, then we can't reuse the same connection for both (or need to introduce a double indirection). Or make ibase_close() effectively a no-op.
 [2016-07-11 09:22 UTC] netvicious at gmail dot com
Hi nikic, thanks for assigning the bug.

The code:
$link = ibase_connect($foo);
$link2 = ibase_connect($foo);
ibase_close($link2);

That functions are similar to mysqli, but changing the type of the DB
ibase_connect = mysqli_connect
ibase_close = mysqli_close

If you close $link2, $link should remain open and working.

The current problem it's when you're creating a new connection to a database which has another connection opened before in the same script. The first one should remain open and working instead of being closed as it's done with the current interbase module.
 [2016-12-06 10:32 UTC] us at menatwork dot de
This bug is still present in version 7.1.0 for Windows
 [2016-12-13 22:33 UTC] m dot muncke at computer1020 dot at
Hello,

I have this problem in freeBSD port ver. 7.0.11 and upgrading to 7.0.14 did not solve the issue. Can we have a release estimate when this fix will be included?

Thank you
M.Muncke
 [2017-01-23 12:57 UTC] netvicious at gmail dot com
Hi!

It seems we don't had any progress on this bug from a long time ago.

Nikic, the patch you published didn't worked and the question you did on 2016-07-10 obviously it's yes, if we close the conx2 the conx1 should be kept as it was before.

But the problem it's not when we're closing links, the problem it's when we're connecting a new link. On this process the old link it's closed. It seems to be using a variable for the only one link supported instead of using a list and closing the correct index of the link of the list.

If you do a simple echo with the link you can see the links are numbered

$conx = ibase_pconnect(DB_HOST . ":" . DB_NAME,DB_USER,DB_PWD,DB_CHARACTER) or die(ibase_errcode() . ' ' . ibase_errmsg()); 
echo $conx . "<br/>\n";

$conx2 = ibase_pconnect(DB_HOST . ":" . DB_NAME,DB_USER,DB_PWD,DB_CHARACTER) or die(ibase_errcode() . ' ' . ibase_errmsg()); 
echo $conx2 . "<br/>\n";

If the connections are ok you should get something like:
Resource id #1
Resource id #2

The system it's saving the connections in order.

The problem should be in some place where it checks if that link was previously connected to database (or in the garbage collector).

A similar code should be on the mysql connections and other database drivers.

I know you tried to fix it, but I ask you to ask to other php developers which know a bit others database drivers; because that piece of code should be very similar between drivers.

Regards,
 [2017-01-23 13:48 UTC] nikic@php.net
-Status: Assigned +Status: Open -Assigned To: nikic +Assigned To:
 [2017-01-23 14:12 UTC] us at menatwork dot de
I did the tests with Windows. In Version 7.0.0 and 5.6.28 everything is ok. The error comes into with Version 7.0.3.

I am not a C Programmer, but is it so dificult to find the difference between 7.0.0 and 7.0.3 ?
 [2017-01-23 14:30 UTC] netvicious at gmail dot com
Between 7.0.2 and 7.0.3 there are a lot of chantes (7.0.0 to 7.0.3 the list it's bigger).

**7.0.2**************************************************************************
		xlink = (zend_resource*) le->ptr;
		if ((!persistent && xlink->type == le_link) || xlink->type == le_plink) {
			if (IBG(default_link) > 0) {
				zval *link = zend_hash_index_find(&EG(regular_list), IBG(default_link));
				if (link) {
					zend_list_delete(Z_RES_P(link));
				}
			}
			xlink->gc.refcount++;
			xlink->gc.refcount++;
			IBG(default_link) = xlink->handle;
			RETVAL_RES(xlink);
		} else {
			zend_hash_str_del(&EG(regular_list), hash, sizeof(hash)-1);
		}

**7.0.3**************************************************************************
		xlink = (zend_resource*) le->ptr;
		if ((!persistent && xlink->type == le_link) || xlink->type == le_plink) {
			if (IBG(default_link)) {
				zend_list_close(IBG(default_link));
			}
			xlink->gc.refcount++;
			xlink->gc.refcount++;
			IBG(default_link) = xlink;
			RETVAL_RES(xlink);
		} else {
			zend_hash_str_del(&EG(regular_list), hash, sizeof(hash)-1);
		}


They only changed some things related to lists and a way to check the "default_link".

I don't know where it's the problem, but the word default_link says to me something like there only can be one NON-persistent link to the firebird/interbase database.

Because that code it paster before it's inside one if

	/* try to reuse a connection */
	if ((le = zend_hash_str_find_ptr(&EG(regular_list), hash, sizeof(hash)-1)) != NULL) {


And after that if we have something that seems to create a persistent one

	/* ... or a persistent one */
	do {


One thing I don't understand it's if we reused a connection why after the if of reusing connection we do a persistent one.

If it's really one OR the RETVAL should exit the function like one return statement (I don't know if it does a return).
 [2017-04-28 14:17 UTC] fabricio-th at bol dot com dot br
Hallo,

This bug is still present in version 7.1.4 for Windows and Debian
 [2017-07-10 20:33 UTC] fabricio dot th2 at gmail dot com
Hello,

This bug is still present in version 7.2-alpha3 for Windows and Debian;
 [2017-07-12 10:36 UTC] us at menatwork dot de
I think, nobody wants to repair this, so Firebird with PHP is dead.
 [2017-11-10 10:03 UTC] roman dot vanicek at gmail dot com
There is a workaround. One can use one database handle obtained from ibase_connect and then multiple transaction handles obtained from ibase_trans.
 [2017-11-10 11:50 UTC] netvicious at gmail dot com
I sent a comment to the Firebird dev mailing list but anybody looked at this bug. 

As I said my workaround was to use a static var on the database access library I include on all the php files which use BDs.

class ps_DB {

...

private static $conn = 0;

function connect() { 

	if (self::$lid == 0) {
		self::$lid = ibase_pconnect(DB_HOST . ":" . DB_NAME,DB_USER,DB_PWD,DB_CHARACTER);

...

Using this static variable we will use always the same BD connection and it will work.
 [2017-12-04 16:17 UTC] buhlerax@php.net
Good afternoon,
Does anyone have any news about this bug?
I use Debian Jessie with php 7.0, 7.1 and the same situation happens.
 [2018-05-07 19:39 UTC] ucijas at gmail dot com
I can confirm this also in CentOS 6.9 compiling 7.1.17 via github as of today:

Any sub-call to another function which also calls ibase_connect() will break the parent-function's previous ibase connection.

I could theoretically get around it sometimes by creative SQL joins or storing in arrays, if projects were small, but we way too much legacy code to do that, and it would ultimately spaghettify our code anyway.

Thus -- as indicated by "us at menatwork dot de" on 2017/07/12 -- this a complete dead-in-water deal-breaker for PHP 7+ w/Firebird and, until fixed, there really should be prominent warnings put out (home page, changelog, release notes, and compilation script) that PHP 7+ does not work with Firebird and not to waste folks' time.

Let me know if I can be of any help. I may be able to look at the code later, but my C++ is rusty and I am now up against deadlines, so this keeps us at 5.6.

See also Bug #14039 (https://bugs.php.net/bug.php?id=14039). Seems to have existed for a while back 2002, as well, then was fixed, then popped up again in 2017. (Might be related?)

Thanks.
 [2018-05-08 06:50 UTC] NetVicious at gmail dot com
#14039 it's related to the garbage collector. This bug it's related with the Interbase engine which received some change on the 7.0 branch, and doesn't allows to create two different connections to the same database at the same time.

To start working with 7.X branch you can use my workaround using a static variable for the database connection (check my message of 2017-11-10 11:50 UTC on this page).
 [2018-06-20 19:58 UTC] lester at lsces dot co dot uk
"It seems $conx has been closed when creating the $conx2 connection."

But if you check the manual on ibase_connect, using the same connection details results in the existing connection just being copied. So there should be no attempt to create a new connection. I think the older code was trying to pick up when the same link was being used, while the amended code seems to miss that act?

Currently waiting on a clone of the php-src updating from Feb17 to current. Only another 17500 commits to go, the I can track the implemented changes.
 [2018-11-26 17:49 UTC] netvicious at gmail dot com
Interbase module seems to be abandoned. All the developers which appear on phpinfo() related with the Interbase/firebird module are not active developers of php looking at their Linkedin accounts.

So obviously this bug won't be fixed because there it's no active developer in charge of the interbase/firebird module.

I think the module was ported to PHP 7.0 by someon which doesn't know the previous module and that's why it has bugs like this one.
 [2018-12-20 08:44 UTC] netvicious at gmail dot com
-Summary: Impossibility of creatiing multiple connections to Interbase with php 7.0 +Summary: Impossibility of creating multiple connections to Interbase with php 7.x -PHP Version: 7.0.6 +PHP Version: 7.x
 [2018-12-20 08:44 UTC] netvicious at gmail dot com
Summary and PHP Version modified.
 [2018-12-20 13:57 UTC] cmb@php.net
> If it's really one OR the RETVAL should exit the function like one
> return statement (I don't know if it does a return).

Indeed, the RETVAL_RES(xlink) should likely be RETURN_RES(xlink).

> Interbase module seems to be abandoned.

Unfortunately, yes.

> I think the module was ported to PHP 7.0 by someon which doesn't
> know the previous module […]

It has been proposed to remove the unmainted ext/interbase for PHP
7[1], but somebody claimed to be willing to maintain it.
Unfortunately, that didn't really happen, but instead of removing
the extension belatedly, we'd tried to fix it[2] …

[1] <https://wiki.php.net/rfc/removal_of_dead_sapis_and_exts#extinterbase>
[2] <https://externals.io/message/89858>
 [2018-12-21 08:31 UTC] netvicious at gmail dot com
Thanks for the info Christoph. The module works perfectly, almost for me. This it's the only bug I found which made me change some code to workaround it.

Firebird/Interbase DBMS it's live yet, Firebird will release version 4 in some time, and Interbase it's maintained by Embarcadero. So it will be a pity if PHP doesn't has a native driver for it.

As you said the module it's currently not maintained by a PHP developer and that's why this bug it's unfixed yet.

It's there anyway we can help. I read something about there it's not an environment test to check if the code works ...
 [2019-01-01 19:21 UTC] umberto dot masotti at unich dot it
Even in the way to help maintaining, why PHP site build setup instrunctions are 5 years old?

http://it2.php.net/build-setup.php

or

https://secure.php.net/build-setup.php

To be sure, follow "Get involved" and click in the right pane "Developer Setup Help" 
The "some helpful information regarding setting up a development environment for PHP" actually are not.

Trying to setup an Ubuntu PHP7 VM to check what can be done, but for Windows don't know if I can in spare time.
 [2019-03-22 16:19 UTC] nikic@php.net
Here is a possible patch against the PHP 7.3 branch: https://gist.github.com/nikic/ef81684007753232893eae7acc034196

This should resolve this issue and some of the other more blatant refcounting bugs. Because it does so, it may also change the behavior of ibase_close to close all shared connections. I've added a hack to avoid closing the default link, but it may be better to just make ibase_close a no-op instead.
 [2019-03-23 15:33 UTC] lester at lsces dot co dot uk
I have a test running on 7.2.16 ...
http://smallbrook.co.uk:800/ibtest2.php

http://smallbrook.co.uk:800/ibtest3.php creates a connection to a second database and then 2 to the example database ... so Resource id #3 is duplicated nicely ...

It is worth pointing out that the problem was never with creating multiple connections, but rather with trying to start a second connection to the same database. In reality all that is required is to simply use the existing connection, and nikita's patch neatly restores that operation under the hood. It simply returns the existing resource handle when a duplicate database is used.
 [2019-03-25 07:27 UTC] martin dot koeditz at it-syn dot de
Hello Nikita, hello Lester

I am also working on a patch. So I thought, I inform you about this.

I will check Nikita's patch too. But looks very promising. If this works, we should check it in.

Regards,
Martin
 [2019-03-25 15:44 UTC] nikic@php.net
Automatic comment on behalf of nikita.ppv@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=85095dfd0956bc09f5157211948c40cfa2859d27
Log: Fixed bug #72175
 [2019-03-25 15:44 UTC] nikic@php.net
-Status: Open +Status: Closed
 [2019-03-25 15:48 UTC] nikic@php.net
-Assigned To: +Assigned To: nikic
 [2019-03-25 15:48 UTC] nikic@php.net
I've now applied a much more limited version of the previous patch to 7.2 and upwards. It should fix this issue and just this issue. The other changes should still happen, because they fix potential use-after-free and memory leaks, but we should probably wait with those more intrusive changes until the extension has a maintainer.
 [2020-11-12 13:20 UTC] vitorhugohoch at gmail dot com
If you close two connections (rows) with one variable handling the conection like

$conn = "IBASE/FIREBIRD Query path";

(code... $row...)


fbird_free_result($resABC);
fbird_close($conn);


fbird_free_result($resXYZ);
fbird_close($conn);

Get that error but do the query (row):

ibase_fetch_assoc(): invalid statement handle

I dont' know if this is an error.

If it is an error, would it be impossible to close multiple results with a connection on the same page?
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Mon Oct 14 05:01:28 2024 UTC