Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ReleasePreparedCommands method in FbConnectionInternal does not work as expected - does not release resources of all prepared commands upon connection close. [DNET421] #419

Closed
firebird-automations opened this issue Mar 12, 2012 · 5 comments

Comments

@firebird-automations
Copy link

Submitted by: Jiří Farták (genx)

Is related to DNET291

Here's excerpt of the problematic method:

public void ReleasePreparedCommands()
{
for (int i = 0; i < this.preparedCommands.Count; i++)
{
if (!this.preparedCommands[i].IsAlive)
continue;

                                                           try
                                                           \{
                                                                          // Release statement handle
                                                                          \(this\.preparedCommands\[i\]\.Target as FbCommand\)\.Release\(\);

...
}

Collection of preparedCommands that is being processed is changed due to side effect by the FbCommand.Release() call - this function indirectly calls preparedCommands.RemoveAt(i), that causes collection item (index) shifting and changing the Count property value in the for-cycle condition. The change of Count property is not problem. The problem is that unconditional increment of condition control variable "i" at each cycle causes skipping of the item that follows the released one due to mentioned item shifting after RemoveAt(i) method call (item at index "i" is removed, thus following item gets to its position to "fill the gap", but "i" is increased at next for-cycle, so this item is skipped). By other words, if no prepared command was in Alive state, then each even prepared command is properly released.

Due to this bug, not all prepared commands are released - mainly their referenced Statement objects. This could lead to throwing exceptions when core of the driver works with non-properly released resources of FbCommand objects when they are about to be reused after database connection close and not disposed immediately. Such Statement objects are considered valid (but they reference GdsDatabase object that has input and outputStream properties filled with null values etc.) and they are not recreated upon new database connection and executing the reused FbCommand.

One can avoid of this bug, if the FbCommand objects are not reused after connection close (by assigning new Connection and eventually Transaction to them), but diposed and recreated again.

We observed the driver throwing NullPointerExceptions at GdsDatabase.Write() methods when calling FbCommand.ExecuteXXX methods, because FbCommand referenced invalid, previously unreleased Statement object, that referenced invalid old GdsDatabase object.

Commits: d00a37a

@firebird-automations
Copy link
Author

Modified by: @cincuranet

status: Open [ 1 ] => In Progress [ 3 ]

@firebird-automations
Copy link
Author

Modified by: @cincuranet

status: In Progress [ 3 ] => Resolved [ 5 ]

resolution: Fixed [ 1 ]

Fix Version: 2.7-next [ 10462 ]

@firebird-automations
Copy link
Author

Commented by: @cincuranet

Was the exception really NullPointerException? Wasn't it NullReferenceException? I have a feeling, that's same as DNET291, isn't it?

@firebird-automations
Copy link
Author

Modified by: @cincuranet

Link: This issue is related to DNET291 [ DNET291 ]

@firebird-automations
Copy link
Author

Commented by: Jiří Farták (genx)

Yep. You're right, my typo - Null Referrence Exceptions are right.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants