summaryrefslogtreecommitdiffstats
path: root/database/engine
diff options
context:
space:
mode:
authorMarkos Fountoulakis <44345837+mfundul@users.noreply.github.com>2019-05-22 13:27:54 +0300
committerChris Akritidis <43294513+cakrit@users.noreply.github.com>2019-05-22 12:27:54 +0200
commit908d5c78faf0356ec2bfe91db0eae06f47785b39 (patch)
tree431d12e5200a8c1ea630fa83ff5e723acb686f66 /database/engine
parentc065099bfee9979a3632a4da90f808785a60ec97 (diff)
Fix race condition in DB engine API (#6079)
Diffstat (limited to 'database/engine')
-rw-r--r--database/engine/pagecache.h1
-rw-r--r--database/engine/rrdengineapi.c8
2 files changed, 8 insertions, 1 deletions
diff --git a/database/engine/pagecache.h b/database/engine/pagecache.h
index d1e29aaab3..9b89edfca6 100644
--- a/database/engine/pagecache.h
+++ b/database/engine/pagecache.h
@@ -114,6 +114,7 @@ extern void pg_cache_replaceQ_delete(struct rrdengine_instance *ctx,
extern void pg_cache_replaceQ_set_hot(struct rrdengine_instance *ctx,
struct rrdeng_page_cache_descr *descr);
extern struct rrdeng_page_cache_descr *pg_cache_create_descr(void);
+extern int pg_cache_try_get_unsafe(struct rrdeng_page_cache_descr *descr, int exclusive_access);
extern void pg_cache_put_unsafe(struct rrdeng_page_cache_descr *descr);
extern void pg_cache_put(struct rrdeng_page_cache_descr *descr);
extern void pg_cache_insert(struct rrdengine_instance *ctx, struct pg_cache_page_index *index,
diff --git a/database/engine/rrdengineapi.c b/database/engine/rrdengineapi.c
index fcd61a115d..4771c43b56 100644
--- a/database/engine/rrdengineapi.c
+++ b/database/engine/rrdengineapi.c
@@ -76,11 +76,17 @@ void rrdeng_store_metric_next(RRDDIM *rd, usec_t point_in_time, storage_number n
if (descr) {
descr->handle = NULL;
if (descr->page_length) {
+ int ret;
+
#ifdef NETDATA_INTERNAL_CHECKS
rrd_stat_atomic_add(&ctx->stats.metric_API_producers, -1);
#endif
/* added 1 extra reference to keep 2 dirty pages pinned per metric, expected refcnt = 2 */
- ++descr->refcnt;
+ uv_mutex_lock(&descr->mutex);
+ ret = pg_cache_try_get_unsafe(descr, 0);
+ uv_mutex_unlock(&descr->mutex);
+ assert (1 == ret);
+
rrdeng_commit_page(ctx, descr, handle->page_correlation_id);
if (handle->prev_descr) {
/* unpin old second page */