From f519b6df21edb10c393b3c32e27b45809d53eddf Mon Sep 17 00:00:00 2001 From: rfm Date: Tue, 18 Oct 2016 08:32:05 +0000 Subject: [PATCH] Don't allow pool clients to be set as database notification observers git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/sqlclient/trunk@40152 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 8 ++++++++ SQLClient.h | 22 ++++++++++++++++++++-- SQLClient.m | 7 ++++++- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index a77af2c..6046125 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2016-10-18 Richard Frith-Macdonald + + * SQLClient.h: + * SQLClient.m: + Make -addObserver:selector:name: raise if applied to a client in a + pool. Improve documentation to make it clear that pool clients + can't be used as observers of database notifications. + 2016-06-23 Richard Frith-Macdonald * SQLClient.m: Fixup to use case sensitive notification names. diff --git a/SQLClient.h b/SQLClient.h index f5b74f7..fb946db 100644 --- a/SQLClient.h +++ b/SQLClient.h @@ -1291,7 +1291,13 @@ SQLCLIENT_PRIVATE * occur inside a transaction is the -begin and -commit statements * are used. For this reason, observing code may want to use the * -lockBeforeDate: -isInTransaction and -unlock methods to ensure - * that they don't interfere with ongoing transactions. + * that they don't interfere with ongoing transactions.
+ * For observation of notifications to be immediately effective, the + * instance must be connected to the database (and remain connected), + * so you can't call this method on a client from a pool, and you should + * make sure that you don't close the client connection (or if you do, + * that you make sure to re-open it in order to start receiving + * notifications again). */ - (void) addObserver: (id)anObserver selector: (SEL)aSelector @@ -1578,6 +1584,13 @@ typedef struct { * method which would be required to be followed up by another message to * the same client. *

+ *

NB. Any client provided from a pool should be returned to the + * pool as soon as reasonably possible (and if left idle will have its + * connection to the server closed anyway) so that it can be used by + * other threads. If you want a permenantly open database connection + * you should use a normal SQLClient instance, not one from a pool. + * You must not call -addObserver:selector:name: on a client from a pool. + *

*/ @interface SQLClientPool : NSObject { @@ -1669,7 +1682,12 @@ typedef struct { * If isLocal is YES, this method provides a client which will not be * used elsewhere in the same thread until/unless the calling code * returns it to the pool. Otherwise (isLocal is NO), the client may - * be used by other code in the same thread. + * be used by other code in the same thread.
+ * NB. Any client provided using this method should be returned to the + * pool as soon as reasonably possible (and if left idle will have its + * connection to the server closed anyway) so that it can be used by + * other threads. If you want a permenantly open database connection + * you should use a normal SQLClient instance, not one from a pool. */ - (SQLClient*) provideClientBeforeDate: (NSDate*)when exclusive: (BOOL)isLocal; diff --git a/SQLClient.m b/SQLClient.m index 89622df..243d3cb 100644 --- a/SQLClient.m +++ b/SQLClient.m @@ -3054,7 +3054,7 @@ static int poolConnections = 0; } else { - /* Not really an asynchronous query becuse we wait until it's + /* Not really an asynchronous query because we wait until it's * done in order to have a result we can return. */ [self performSelectorOnMainThread: @selector(_populateCache:) @@ -3867,6 +3867,11 @@ validName(NSString *name) [NSException raise: NSInvalidArgumentException format: @"Attempt to add nil observer to SQL client"]; } + if (nil != _pool) + { + [NSException raise: NSInvalidArgumentException + format: @"Attempt to use pool client as observer"]; + } name = validName(name); [lock lock]; NS_DURING