On 09/30/2011 02:21 PM, Scott Morgan wrote:
On 09/30/2011 12:59 PM, Mark Rotteveel wrote:
True, but making sure that you always lock resources in the same order,
is the only sure way to prevent deadlocks.
I think I see the problem:

In Version10/GdsTransaction.cs (copy/paste from the Sourceforge SVN
browser, so excuse the formatting)
...
The SyncObject lock is to protect the calls to this.database.Write etc.
(lines 194-200) but it also covers the transaction's state change (lines
202-207) which it shouldn't and is the point the deadlock occurs.

Something like this may be better:
...
Similar changes would need to be made to the other functions in this
class (Commit, RollbackRetaining, etc...)

Scott

See patch against the SVN trunk.

Scott

Index: GdsServiceManager.cs
===================================================================
--- GdsServiceManager.cs        (revision 53626)
+++ GdsServiceManager.cs        (working copy)
@@ -64,15 +64,18 @@
                        {
                                try
                                {
-                                       
this.database.Write(IscCodes.op_service_attach);
-                                       this.database.Write(0);
-                                       this.database.Write(service);
-                                       
this.database.WriteBuffer(spb.ToArray());
-                                       this.database.Flush();
+                                       lock (this.database.SyncObject)
+                                       {
+                                               
this.database.Write(IscCodes.op_service_attach);
+                                               this.database.Write(0);
+                                               this.database.Write(service);
+                                               
this.database.WriteBuffer(spb.ToArray());
+                                               this.database.Flush();
 
-                    response = this.database.ReadGenericResponse();
+                                               response = 
this.database.ReadGenericResponse();
+                                       }
 
-                    this.handle = response.ObjectHandle;
+                                       this.handle = response.ObjectHandle;
                                }
                                catch (IOException)
                                {
@@ -89,12 +92,15 @@
                        {
                                try
                                {
-                                       
this.database.Write(IscCodes.op_service_detach);
-                                       this.database.Write(this.Handle);
-                                       
this.database.Write(IscCodes.op_disconnect);
-                                       this.database.Flush();
+                                       lock (this.database.SyncObject)
+                                       {
+                                               
this.database.Write(IscCodes.op_service_detach);
+                                               
this.database.Write(this.Handle);
+                                               
this.database.Write(IscCodes.op_disconnect);
+                                               this.database.Flush();
 
-                                       this.database.ReadResponse();
+                                               this.database.ReadResponse();
+                                       }
 
                                        this.handle = 0;
                                }
@@ -127,20 +133,23 @@
                        {
                                try
                                {
-                                       
this.database.Write(IscCodes.op_service_start);
-                                       this.database.Write(this.Handle);
-                                       this.database.Write(0);
-                                       
this.database.WriteBuffer(spb.ToArray(), spb.Length);
-                                       this.database.Flush();
+                                       lock (this.database.SyncObject)
+                                       {
+                                               
this.database.Write(IscCodes.op_service_start);
+                                               
this.database.Write(this.Handle);
+                                               this.database.Write(0);
+                                               
this.database.WriteBuffer(spb.ToArray(), spb.Length);
+                                               this.database.Flush();
 
-                                       try
-                                       {
-                                               this.database.ReadResponse();
+                                               try
+                                               {
+                                                       
this.database.ReadResponse();
+                                               }
+                                               catch (IscException)
+                                               {
+                                                       throw;
+                                               }
                                        }
-                                       catch (IscException)
-                                       {
-                                               throw;
-                                       }
                                }
                                catch (IOException)
                                {
@@ -160,27 +169,30 @@
                        {
                                try
                                {
-                                       
this.database.Write(IscCodes.op_service_info);  //      operation
-                                       this.database.Write(this.Handle);       
                        //      db_handle
-                                       this.database.Write(0);                 
                                //      incarnation                             
        
-                                       this.database.WriteTyped(
-                                               IscCodes.isc_spb_version, 
spb.ToArray());       //      Service parameter buffer
-                                       this.database.WriteBuffer(
-                                               requestBuffer, requestLength);  
                        //      request buffer
-                                       this.database.Write(bufferLength);      
                        //      result buffer length
+                                       lock (this.database.SyncObject)
+                                       {
+                                               
this.database.Write(IscCodes.op_service_info);  //      operation
+                                               
this.database.Write(this.Handle);                               //      
db_handle
+                                               this.database.Write(0);         
                                        //      incarnation                     
                
+                                               this.database.WriteTyped(
+                                                       
IscCodes.isc_spb_version, spb.ToArray());       //      Service parameter buffer
+                                               this.database.WriteBuffer(
+                                                       requestBuffer, 
requestLength);                          //      request buffer
+                                               
this.database.Write(bufferLength);                              //      result 
buffer length
 
-                                       this.database.Flush();
+                                               this.database.Flush();
 
-                                       GenericResponse response = 
this.database.ReadGenericResponse();
+                                               GenericResponse response = 
this.database.ReadGenericResponse();
 
-                    int responseLength = bufferLength;
+                                               int responseLength = 
bufferLength;
 
-                    if (response.Data.Length < bufferLength)
-                    {
-                        responseLength = response.Data.Length;
-                    }
+                                               if (response.Data.Length < 
bufferLength)
+                                               {
+                                                       responseLength = 
response.Data.Length;
+                                               }
 
-                    Buffer.BlockCopy(response.Data, 0, buffer, 0, 
responseLength);
+                                               Buffer.BlockCopy(response.Data, 
0, buffer, 0, responseLength);
+                                       }
                                }
                                catch (IOException)
                                {
Index: GdsTransaction.cs
===================================================================
--- GdsTransaction.cs   (revision 53626)
+++ GdsTransaction.cs   (working copy)
@@ -125,26 +125,29 @@
 
                public void BeginTransaction(TransactionParameterBuffer tpb)
                {
-                       if (this.state != TransactionState.NoTransaction)
+                       lock (this)
                        {
-                               throw new IscException(IscCodes.isc_arg_gds, 
IscCodes.isc_tra_state, this.handle, "no valid");
-                       }
+                               if (this.state != 
TransactionState.NoTransaction)
+                               {
+                                       throw new 
IscException(IscCodes.isc_arg_gds, IscCodes.isc_tra_state, this.handle, "no 
valid");
+                               }
 
-                       lock (this.database.SyncObject)
-                       {
                                try
                                {
-                                       
this.database.Write(IscCodes.op_transaction);
-                                       
this.database.Write(this.database.Handle);
-                                       
this.database.WriteBuffer(tpb.ToArray());
-                                       this.database.Flush();
+                                       lock (this.database.SyncObject)
+                                       {
+                                               
this.database.Write(IscCodes.op_transaction);
+                                               
this.database.Write(this.database.Handle);
+                                               
this.database.WriteBuffer(tpb.ToArray());
+                                               this.database.Flush();
 
-                    GenericResponse response = 
this.database.ReadGenericResponse();
+                                               GenericResponse response = 
this.database.ReadGenericResponse();
 
-                    this.handle = response.ObjectHandle;
-                                       this.state  = TransactionState.Active;
+                                               this.handle = 
response.ObjectHandle;
+                                               this.state = 
TransactionState.Active;
 
-                                       this.database.TransactionCount++;
+                                               
this.database.TransactionCount++;
+                                       }
                                }
                                catch (IOException)
                                {
@@ -155,19 +158,22 @@
 
                public void Commit()
                {
-                       this.CheckTransactionState();
+                       lock (this)
+                       {
+                               this.CheckTransactionState();
 
-                       lock (this.database.SyncObject)
-                       {
                                try
                                {
-                                       this.database.Write(IscCodes.op_commit);
-                                       this.database.Write(this.handle);
-                                       this.database.Flush();
+                                       lock (this.database.SyncObject)
+                                       {
+                                               
this.database.Write(IscCodes.op_commit);
+                                               
this.database.Write(this.handle);
+                                               this.database.Flush();
 
-                                       this.database.ReadResponse();
+                                               this.database.ReadResponse();
 
-                                       this.database.TransactionCount--;
+                                               
this.database.TransactionCount--;
+                                       }
 
                                        if (this.Update != null)
                                        {
@@ -185,19 +191,22 @@
 
                public void Rollback()
                {
-                       this.CheckTransactionState();
+                       lock (this)
+                       {
+                               this.CheckTransactionState();
 
-                       lock (this.database.SyncObject)
-                       {
                                try
                                {
-                                       
this.database.Write(IscCodes.op_rollback);
-                                       this.database.Write(this.handle);
-                                       this.database.Flush();
+                                       lock (this.database.SyncObject)
+                                       {
+                                               
this.database.Write(IscCodes.op_rollback);
+                                               
this.database.Write(this.handle);
+                                               this.database.Flush();
 
-                                       this.database.ReadResponse();
+                                               this.database.ReadResponse();
 
-                                       this.database.TransactionCount--;
+                                               
this.database.TransactionCount--;
+                                       }
 
                                        if (this.Update != null)
                                        {
@@ -215,17 +224,20 @@
 
                public void CommitRetaining()
                {
-                       this.CheckTransactionState();
+                       lock (this)
+                       {
+                               this.CheckTransactionState();
 
-                       lock (this.database.SyncObject)
-                       {
                                try
                                {
-                                       
this.database.Write(IscCodes.op_commit_retaining);
-                                       this.database.Write(this.handle);
-                                       this.database.Flush();
+                                       lock (this.database.SyncObject)
+                                       {
+                                               
this.database.Write(IscCodes.op_commit_retaining);
+                                               
this.database.Write(this.handle);
+                                               this.database.Flush();
 
-                                       this.database.ReadResponse();
+                                               this.database.ReadResponse();
+                                       }
 
                                        this.state = TransactionState.Active;
                                }
@@ -238,17 +250,20 @@
 
                public void RollbackRetaining()
                {
-                       this.CheckTransactionState();
+                       lock (this)
+                       {
+                               this.CheckTransactionState();
 
-                       lock (this.database.SyncObject)
-                       {
                                try
                                {
-                                       
this.database.Write(IscCodes.op_rollback_retaining);
-                                       this.database.Write(this.handle);
-                                       this.database.Flush();
+                                       lock (this.database.SyncObject)
+                                       {
+                                               
this.database.Write(IscCodes.op_rollback_retaining);
+                                               
this.database.Write(this.handle);
+                                               this.database.Flush();
 
-                                       this.database.ReadResponse();
+                                               this.database.ReadResponse();
+                                       }
 
                                        this.state = TransactionState.Active;
                                }
@@ -263,56 +278,62 @@
 
         #region · Two Phase Commit Methods ·
 
-        public void Prepare()
-        {
-            this.CheckTransactionState();
+               public void Prepare()
+               {
+                       lock (this)
+                       {
+                               this.CheckTransactionState();
 
-            lock (this.database.SyncObject)
-            {
-                try
-                {
-                    this.state = TransactionState.NoTransaction;
+                               try
+                               {
+                                       this.state = 
TransactionState.NoTransaction;
 
-                    this.database.Write(IscCodes.op_prepare);
-                    this.database.Write(this.handle);
-                    this.database.Flush();
+                                       lock (this.database.SyncObject)
+                                       {
+                                               
this.database.Write(IscCodes.op_prepare);
+                                               
this.database.Write(this.handle);
+                                               this.database.Flush();
 
-                    this.database.ReadResponse();
+                                               this.database.ReadResponse();
+                                       }
 
-                    this.state = TransactionState.Prepared;
-                }
-                catch (IOException)
-                {
-                    throw new IscException(IscCodes.isc_net_read_err);
-                }
-            }
-        }
+                                       this.state = TransactionState.Prepared;
+                               }
+                               catch (IOException)
+                               {
+                                       throw new 
IscException(IscCodes.isc_net_read_err);
+                               }
+                       }
+               }
 
-        public void Prepare(byte[] buffer)
-        {
-            this.CheckTransactionState();
+               public void Prepare(byte[] buffer)
+               {
+                       lock (this)
+                       {
+                               this.CheckTransactionState();
 
-            lock (this.database.SyncObject)
-            {
-                try
-                {
-                    this.state = TransactionState.NoTransaction;
+                               try
+                               {
+                                       this.state = 
TransactionState.NoTransaction;
 
-                    this.database.Write(IscCodes.op_prepare2);
-                    this.database.Write(this.handle);
-                    this.database.WriteBuffer(buffer, buffer.Length);
-                    this.database.Flush();
+                                       lock (this.database.SyncObject)
+                                       {
+                                               
this.database.Write(IscCodes.op_prepare2);
+                                               
this.database.Write(this.handle);
+                                               
this.database.WriteBuffer(buffer, buffer.Length);
+                                               this.database.Flush();
 
-                    this.database.ReadResponse();
+                                               this.database.ReadResponse();
+                                       }
 
-                    this.state = TransactionState.Prepared;
-                }
-                catch (IOException)
-                {
-                    throw new IscException(IscCodes.isc_net_read_err);
-                }
-            }
-        }
+                                       this.state = TransactionState.Prepared;
+                               }
+                               catch (IOException)
+                               {
+                                       throw new 
IscException(IscCodes.isc_net_read_err);
+                               }
+                       }
+               }
 
         #endregion
 
------------------------------------------------------------------------------
RSA(R) Conference 2012
Save $700 by Nov 18
Register now
http://p.sf.net/sfu/rsa-sfdev2dev1
_______________________________________________
Firebird-net-provider mailing list
Firebird-net-provider@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/firebird-net-provider

Reply via email to