diff options
author | Jeremy Allison <jra@samba.org> | 2000-12-15 21:29:06 +0000 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2000-12-15 21:29:06 +0000 |
commit | 99c2693c620cd222da5561d526aa328bec426b77 (patch) | |
tree | 5f524e8a0a8fa929953df69357195ffaf83b68af /source3/tdb | |
parent | 89af6fd745a6f49668bae5b5c2d239d3671fb299 (diff) | |
download | samba-99c2693c620cd222da5561d526aa328bec426b77.tar.gz samba-99c2693c620cd222da5561d526aa328bec426b77.tar.bz2 samba-99c2693c620cd222da5561d526aa328bec426b77.zip |
Added lock backouts on fail.
When chaining together long lines of bloody "if" statements, which should
logically be separated, and one of them allocates memory, remember to
*free* it *WHETHER OR NOT THE IF STATEMENTS SUCCEEDED* !!!!
Yes I do consider this a bug in the coding style of Tridge, Rusty, Tim et al. :-).
I'm just pissed 'cos this took 4 hours to track down even with an insure error report
stating me in the face and also Ben Woodward looking over the code with me :-).
Jeremy.
(This used to be commit 506b5e34c3ba16768dbc82ba21044787de160c45)
Diffstat (limited to 'source3/tdb')
-rw-r--r-- | source3/tdb/tdb.c | 31 |
1 files changed, 28 insertions, 3 deletions
diff --git a/source3/tdb/tdb.c b/source3/tdb/tdb.c index ede38f27f9..afc87b7da0 100644 --- a/source3/tdb/tdb.c +++ b/source3/tdb/tdb.c @@ -922,11 +922,13 @@ TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA oldkey) rec.key_len)) || memcmp(k, oldkey.dptr, oldkey.dsize) != 0) { /* No, it wasn't: unlock it and start from scratch */ - free(k); unlock_record(tdb, tdb->travlocks.off); tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK); tdb->travlocks.off = 0; } + + if (k) + free(k); } if (!tdb->travlocks.off) { @@ -1180,7 +1182,19 @@ int tdb_lockall(TDB_CONTEXT *tdb) /* There are no locks on read-only dbs */ if (tdb->read_only) return TDB_ERRCODE(TDB_ERR_LOCK, -1); if (tdb->lockedkeys) return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); - for (i = 0; i < tdb->header.hash_size; i++) tdb_lock(tdb, i, F_WRLCK); + for (i = 0; i < tdb->header.hash_size; i++) + if (tdb_lock(tdb, i, F_WRLCK)) + break; + + /* If error, release locks we have... */ + if (i < tdb->header.hash_size) { + u32 j; + + for ( j = 0; j < i; j++) + tdb_unlock(tdb, j, F_WRLCK); + return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); + } + return 0; } void tdb_unlockall(TDB_CONTEXT *tdb) @@ -1211,7 +1225,18 @@ int tdb_lockkeys(TDB_CONTEXT *tdb, u32 number, TDB_DATA keys[]) tdb->lockedkeys[j+1] = hash; } /* Finally, lock in order */ - for (i = 0; i < number; i++) tdb_lock(tdb, i, F_WRLCK); + for (i = 0; i < number; i++) + if (tdb_lock(tdb, i, F_WRLCK)) + break; + + /* If error, release locks we have... */ + if (i < number) { + for ( j = 0; j < i; j++) + tdb_unlock(tdb, j, F_WRLCK); + free(tdb->lockedkeys); + tdb->lockedkeys = NULL; + return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); + } return 0; } |