Skip to content

Commit cdafd96

Browse files
author
David Berry
committed
Bug fix for locator locking code
1 parent 79688ec commit cdafd96

File tree

4 files changed

+79
-29
lines changed

4 files changed

+79
-29
lines changed

dat1HandleLock.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
* otherwise (in which case the current thread does not have a lock,
6363
* but some other threads may have read locks). If "recurs" is
6464
* non-zero, +1 is returned only if the supplied Handle and all
65-
* child handles are by the current thread. Otherwise, the
65+
* child handles are locked by the current thread. Otherwise, the
6666
* returned value relates to the first handle (either the supplied
6767
* or a child handle) that was no locked by the current thread.
6868
*
@@ -265,7 +265,7 @@ Handle *dat1HandleLock( Handle *handle, int oper, int recurs, int rdonly,
265265
if( child ) {
266266

267267
/* Get the lock status of the child. */
268-
(void) dat1HandleLock( child, -2, 1, rdonly, &child_result,
268+
(void) dat1HandleLock( child, -1, 1, rdonly, &child_result,
269269
status );
270270

271271
/* If it's 2, we can set the final result and exit immediately. */
@@ -394,7 +394,7 @@ Handle *dat1HandleLock( Handle *handle, int oper, int recurs, int rdonly,
394394
child = handle->children[ichild];
395395
if( child ) {
396396
error_handle = dat1HandleLock( child, -2, 1, rdonly,
397-
&child_result, status );
397+
result, status );
398398
if( error_handle ) break;
399399
}
400400
}
@@ -455,7 +455,7 @@ Handle *dat1HandleLock( Handle *handle, int oper, int recurs, int rdonly,
455455
child = handle->children[ichild];
456456
if( child ) {
457457
error_handle = dat1HandleLock( child, -3, 1, 0,
458-
&child_result, status );
458+
result, status );
459459
if( error_handle ) break;
460460
}
461461
}

datLock.c

+7-8
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,10 @@
2121
* recurs = int (Given)
2222
* If the supplied object is locked successfully, and "recurs" is
2323
* non-zero, then an attempt is made to lock any component objects
24-
* contained within the supplied object. No error is reported if
25-
* any components cannot be locked due to being locked already by
26-
* a different thread - such components are left unchanged. This
27-
* operation is recursive - any children of the child components
28-
* are also locked, etc.
24+
* contained within the supplied object. An error is reported if
25+
* any components cannot be locked due to them being locked already
26+
* by a different thread. This operation is recursive - any children
27+
* of the child components are also locked, etc.
2928
* readonly = int (Given)
3029
* If non-zero, the object (and child objects if "recurs" is non-zero)
3130
* is locked for read-only access. Otherwise it is locked for
@@ -72,9 +71,9 @@
7271
7372
* Notes:
7473
* - An error will be reported if the supplied object is currently
75-
* locked by another thread, but no error is reported if any component
76-
* objects contained within the supplied object are locked by other
77-
* threads (such objects are left unchanged).
74+
* locked by another thread. If "recurs" is non-zero, an error is
75+
* also reported if any component objects contained within the
76+
* supplied object are locked by other threads.
7877
* - The majority of HDS functions will report an error if the object
7978
* supplied to the function has not been locked for use by the calling
8079
* thread. The exceptions are the functions that manage these locks -

datUnlock.c

+4-6
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,15 @@
2121
* recurs = int (Given)
2222
* If the supplied object is unlocked successfully, and "recurs" is
2323
* non-zero, then an attempt is made to unlock any component objects
24-
* contained within the supplied object. No error is reported if
25-
* any components cannot be unlocked due to being locked already by
26-
* a different thread - such components are left unchanged. This
27-
* operation is recursive - any children of the child components
28-
* are also unlocked, etc.
24+
* contained within the supplied object.
2925
* status = int* (Given and Returned)
3026
* Pointer to global status.
3127
3228
* Description:
3329
* This function removes a lock on the supplied HDS object. An error
34-
* is reported if the current thread has no lock to be removed. See
30+
* is reported if the object is not locked by the current thread. If
31+
* "recurs" is non-zero, an error will be reported if any child component
32+
* within the supplied object is not locked by the current thread. See
3533
* datLock.
3634
*
3735
* The object must be locked again, using datLock, before it can be

hdsTest.c

+64-11
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
#include <stdio.h>
6969
#include <inttypes.h>
7070
#include <string.h>
71+
#include <pthread.h>
7172

7273
static void traceme (const HDSLoc * loc, const char * expected, int explev,
7374
int *status);
@@ -81,6 +82,8 @@ static void testThreadSafety( const char *path, int *status );
8182
static void *test1ThreadSafety( void *data );
8283
static void *test2ThreadSafety( void *data );
8384
static void *test3ThreadSafety( void *data );
85+
void showloc( HDSLoc *loc, const char *title, int ind );
86+
void showhan( Handle *h, int ind );
8487

8588
typedef struct threadData {
8689
HDSLoc *loc;
@@ -90,6 +93,9 @@ typedef struct threadData {
9093
int status;
9194
} threadData;
9295

96+
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
97+
98+
9399
int main (void) {
94100

95101
/* Local Variables: */
@@ -1161,7 +1167,9 @@ static void testThreadSafety( const char *path, int *status ) {
11611167
}
11621168

11631169
/* Attempt to access the two top-level objects in two separate threads.
1164-
Each thread attempt to lock the object read/write, but only one can win.
1170+
Each thread attempt to lock the object read/write, but only one can
1171+
win (assuming that the second thread starts up before the first thread
1172+
has finished and unlocked the object).
11651173
The other should report an error. */
11661174
if( *status == SAI__OK ) {
11671175
threaddata1.id = 1;
@@ -1197,9 +1205,6 @@ static void testThreadSafety( const char *path, int *status ) {
11971205
threaddata1.failed + threaddata2.failed );
11981206
}
11991207

1200-
/* Unlock them now that the test has completed. */
1201-
datUnlock( loc1, 1, status );
1202-
datUnlock( loc1b, 1, status );
12031208
}
12041209

12051210
/* Attempt to access the two top-level objects in two separate threads.
@@ -1236,10 +1241,6 @@ static void testThreadSafety( const char *path, int *status ) {
12361241
"- expected 0 to fail.", status,
12371242
threaddata1.failed + threaddata2.failed );
12381243
}
1239-
1240-
/* Unlock them now that the test has completed. */
1241-
datUnlock( loc1, 1, status );
1242-
datUnlock( loc1b, 1, status );
12431244
}
12441245

12451246
/* Lock both top level locators for read-only use by the current thread. The
@@ -1410,23 +1411,42 @@ void *test2ThreadSafety( void *data ) {
14101411
HDSLoc *loc2 = NULL;
14111412
int status = SAI__OK;
14121413
int expect = tdata->rdonly ? 3 : 1;
1414+
int i, ii;
14131415

14141416
datLock( loc1, 1, tdata->rdonly, &status );
14151417
if( status == DAT__THREAD ) {
14161418
emsAnnul( &status );
14171419
tdata->failed = 1;
1418-
} else {
1420+
} else if( status == SAI__OK ){
1421+
14191422
tdata->failed = 0;
14201423
datFind( loc1, "Records", &loc2, &status );
14211424

14221425
/* Check the component locator is locked by the current thread. */
1423-
if( datLocked( loc2, 1, &status ) != expect && status == SAI__OK ) {
1426+
ii = datLocked( loc2, 1, &status );
1427+
if( ii != expect && status == SAI__OK ) {
14241428
status = DAT__FATAL;
14251429
emsRepf("", "testThreadSafety error B1: loc2 is not locked by "
1426-
"current thread.", &status );
1430+
"current thread (%d %d). ", &status, ii, expect );
14271431

14281432
}
14291433
datAnnul( &loc2, &status );
1434+
1435+
/* Do something time consuming to make it likely that this thread
1436+
will not have finished (and so unlocked the object), before the other
1437+
thread starts. */
1438+
for( i = 0; i < 1000000; i++ ) {
1439+
ii = datLocked( loc1, 1, &status );
1440+
if( ii != expect && status == SAI__OK ) {
1441+
status = SAI__ERROR;
1442+
emsRepf( " ", "test2ThreadSafety: Unexpected lock status %d - "
1443+
"expected %d", &status, ii, expect );
1444+
break;
1445+
}
1446+
}
1447+
1448+
datUnlock( loc1, 1, &status );
1449+
14301450
}
14311451

14321452
tdata->status = status;
@@ -1481,3 +1501,36 @@ void *test3ThreadSafety( void *data ) {
14811501

14821502

14831503

1504+
/* Display information about the locs on a locator. */
1505+
void showloc( HDSLoc *loc, const char *title, int indent ) {
1506+
int i;
1507+
pthread_mutex_lock(&mutex);
1508+
printf("\n");
1509+
for( i = 0; i < indent; i++ ) printf(" ");
1510+
printf( "%s\n", title );
1511+
for( i = 0; i < indent; i++ ) printf(" ");
1512+
for( i = 0; i < strlen(title); i++ ) printf("-");
1513+
printf("\n");
1514+
showhan( loc->handle, indent );
1515+
pthread_mutex_unlock(&mutex);
1516+
}
1517+
1518+
void showhan( Handle *h, int indent ) {
1519+
if( !h ) return;
1520+
1521+
int i;
1522+
for( i = 0; i < indent; i++ ) printf(" ");
1523+
printf("'%s' ", h->name ? h->name : " " );
1524+
if( h->nwrite_lock ) printf("w:%zu ", h->write_locker );
1525+
for( i = 0; i < h->nread_lock; i++ ) {
1526+
printf("r:%zu ", h->read_lockers[ i ] );
1527+
}
1528+
printf("\n");
1529+
1530+
for( i = 0; i < h->nchild; i++ ) {
1531+
showhan( h->children[i], indent + 3 );
1532+
}
1533+
}
1534+
1535+
1536+

0 commit comments

Comments
 (0)