Skip to content

Reusing the same connection between threads/commands is not thread safe #1027

@Schnutzel

Description

@Schnutzel

When I reuse a connection between two commands on two different threads (not in parallel), I might run into a race condition. See example:

Using command1 with connection1:

FbCommand command1 = ...
void f() {
  command1.Connection = connection1;
  command1.ExecuteNonQuery();
  // command1.Connection = null;
}

Then, after f has finished:

void g() {
  command1.Connection = connection2;
  command1.ExecuteNonQuery();
}

Meanwhile in a different thread (after f has finished as well):

FbCommand command2 = ...
void h() {
  command2.Connection = connection1;
  command2.ExecuteNonQuery();
}

command1.Connection = connection2 releases connection1 from command1 which indirectly invokes connection1.InnerConnection.RemovePreparedCommand(). However, if g and h are executed at the same time, this can cause both threads to attempts accessing connection1.InnerConnection._preparedCommands, potentially causing this exception (or something similar):

System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
   at System.Collections.Generic.HashSet`1.Enumerator.MoveNext()
   at FirebirdSql.Data.FirebirdClient.FbConnectionInternal.TransactionCompleted()
   at FirebirdSql.Data.FirebirdClient.FbTransaction.CompleteTransaction()
   at FirebirdSql.Data.FirebirdClient.FbTransaction.Commit()
   at FirebirdSql.Data.FirebirdClient.FbCommand.CommitImplicitTransaction()
   at FirebirdSql.Data.FirebirdClient.FbCommand.ExecuteNonQuery()

My current workarounds are:

  1. Set command1.Connection = null immediately when the connection is no longer used by command1 (the commented out line in f)
  2. Avoid reusing the connection altogether.

Is this an actual issue? am I using this wrong? Should I avoid reusing the same connection between thread/commands altogether, or simply setting Connecton=null should be enough?

Thanks!

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions