summaryrefslogtreecommitdiff
path: root/src/c
diff options
context:
space:
mode:
authorGravatar Ziv Scully <ziv@mit.edu>2015-11-20 10:51:43 -0500
committerGravatar Ziv Scully <ziv@mit.edu>2015-11-20 10:51:43 -0500
commit081f815b457cdfe759b733a9adc18aab32127e45 (patch)
treec57fb206444a789c35075e3f2613dd954fba4d58 /src/c
parenta0d66adaeceaa07e4006a0570211f7453a5b5738 (diff)
Tiny concurrency bugfix (race condition on cache->timeNow).
Diffstat (limited to 'src/c')
-rw-r--r--src/c/urweb.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/src/c/urweb.c b/src/c/urweb.c
index 54135666..12009f02 100644
--- a/src/c/urweb.c
+++ b/src/c/urweb.c
@@ -4617,7 +4617,8 @@ static void uw_Sqlcache_add(uw_Sqlcache_Cache *cache, uw_Sqlcache_Entry *entry,
}
static unsigned long uw_Sqlcache_getTimeNow(uw_Sqlcache_Cache *cache) {
- return ++cache->timeNow;
+ // TODO: verify that this makes time comparisons do the Right Thing.
+ return cache->timeNow++;
}
static unsigned long uw_Sqlcache_timeMax(unsigned long x, unsigned long y) {
@@ -4689,7 +4690,7 @@ uw_Sqlcache_Value *uw_Sqlcache_check(uw_context ctx, uw_Sqlcache_Cache *cache, c
// Returning outside the lock is safe because updates happen at commit time.
// Those are the only times the returned value or its strings can get freed.
// Handler output is a new string, so it's safe to free this at commit time.
- return value && value->timeValid > timeInvalid ? value : NULL;
+ return value && timeInvalid < value->timeValid ? value : NULL;
}
static void uw_Sqlcache_storeCommitOne(uw_Sqlcache_Cache *cache, char **keys, uw_Sqlcache_Value *value) {
@@ -4712,7 +4713,7 @@ static void uw_Sqlcache_storeCommitOne(uw_Sqlcache_Cache *cache, char **keys, uw
while (numKeys-- > 0) {
buf = uw_Sqlcache_keyCopy(buf, keys[numKeys]);
size_t len = buf - key;
-
+
entry = uw_Sqlcache_find(cache, key, len, 1);
if (!entry) {
entry = calloc(1, sizeof(uw_Sqlcache_Entry));
@@ -4813,7 +4814,8 @@ void uw_Sqlcache_store(uw_context ctx, uw_Sqlcache_Cache *cache, char **keys, uw
update->keys = uw_Sqlcache_copyKeys(keys, cache->numKeys);
update->value = value;
update->next = NULL;
- value->timeValid = uw_Sqlcache_getTimeNow(cache);
+ // Can't use [uw_Sqlcache_getTimeNow] because it modifies state and we don't have the lock.
+ value->timeValid = cache->timeNow;
if (ctx->cacheUpdateTail) {
ctx->cacheUpdateTail->next = update;
} else {