From 267987d01c9309fee7c3d607444147bf8bbce938 Mon Sep 17 00:00:00 2001 From: Wolfgang Lux Date: Tue, 1 Sep 2020 15:24:16 +0200 Subject: [PATCH] Reinstate fix to avoid deadlock while purging pool --- ChangeLog | 5 +++++ SQLClient.m | 20 ++++++++++++-------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6ce0701..ad00798 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2020-09-01 Wolfgang Lux + + * SQLClient.m (release): Reinstate fix to avoid deadlock while + purging pool. + 2020-04-21 Richard Frith-Macdonald * Postgres.m: Change notification code to de-duplicate notifications diff --git a/SQLClient.m b/SQLClient.m index b1d0e2c..d0136dd 100644 --- a/SQLClient.m +++ b/SQLClient.m @@ -2566,19 +2566,22 @@ static int poolConnections = 0; - (oneway void) release { - /* We lock the table while checking, to prevent - * another thread from grabbing this object while we are - * checking it. - * If we are going to deallocate the object, we first remove - * it from the table so that no other thread will find it - * and try to use it while it is being deallocated. + /* We lock the table while checking, to prevent another thread + * from grabbing this object while we are checking it. */ [clientsLock lock]; if (nil != _pool && [self retainCount] == 1) { - /* If this is the only reference to a client associated with + /* This is the only reference to a client associated with * a connection pool we put this client back to the pool. * + * That being the case, we know that this thread 'owns' + * the client and it's not going to be deallocated and not + * going to have the _pool iinstance variable changed, so it + * is safe to unlock clientsLock before returning the client + * to the pool. This avoids a possible deadlock when a pool + * is being purged. + * * wl 2019-05-01: The original implementation was calling this code * when NSDecrementExtraRefCountWasZero returns YES, but * this does not work with newer versions of the GNUstep @@ -2586,13 +2589,14 @@ static int poolConnections = 0; * Objective-C runtime, which both don't handle resurrection * gracefully for objects whose retain count has become zero. */ + [clientsLock unlock]; [_pool _swallowClient: self explicit: NO]; } else { [super release]; + [clientsLock unlock]; } - [clientsLock unlock]; } - (SQLClientPool*) pool