@cryptotaxi247 / netdata-1 / commits / ea7d7ea31

Fix Coverity defects 359164, 359165 and 358989. (#9268)

Removed uses of the host lock that could deadlock senders and replaced with the new fine-grained mutex.

Andrew Moss committed Jun 4, 2020 at 18:24 UTC ea7d7ea31d2d48730ccaf37e1c96c43f6b255fa8
4 files changed +11 -14
daemon/commands.c
+1 -1
@@ -673,7 +673,7 @@ void commands_init(void)
673
674 info("Initializing command server.");
675 for (i = 0 ; i < CMD_TOTAL_COMMANDS ; ++i) {
676 - uv_mutex_init(&command_lock_array[i]);
676 + assert(0 == uv_mutex_init(&command_lock_array[i]));
677 }
678 assert(0 == uv_rwlock_init(&exclusive_rwlock));
679
streaming/rrdpush.c
+5 -8
@@ -368,12 +368,10 @@ void rrdpush_send_labels(RRDHOST *host) {
368 // rrdpush sender thread
369
370 // Either the receiver lost the connection or the host is being destroyed.
371 -// Don't lock the sender buffer - doesn't affect consistency in either case.
372 -// TODO-GAPS During the host destruction sequence we should make sure the disconnect happens early enough to lock
373 -// out collectors hitting the sender. Locking the mutex means there may be waiting threads when we free.
371 +// The sender mutex guards thread creation, any spurious data is wiped on reconnection.
372 void rrdpush_sender_thread_stop(RRDHOST *host) {
375 - rrdhost_wrlock(host);
373
374 + netdata_mutex_lock(&host->sender->mutex);
375 netdata_thread_t thr = 0;
376
377 if(host->rrdpush_sender_spawn) {
@@ -390,7 +388,7 @@ void rrdpush_sender_thread_stop(RRDHOST *host) {
388 netdata_thread_cancel(host->rrdpush_sender_thread);
389 }
390
393 - rrdhost_unlock(host);
391 + netdata_mutex_unlock(&host->sender->mutex);
392
393 if(thr != 0) {
394 info("STREAM %s [send]: waiting for the sending thread to stop...", host->hostname);
@@ -410,7 +408,7 @@ void log_stream_connection(const char *client_ip, const char *client_port, const
408
409
410 static void rrdpush_sender_thread_spawn(RRDHOST *host) {
413 - rrdhost_wrlock(host);
411 + netdata_mutex_lock(&host->sender->mutex);
412
413 if(!host->rrdpush_sender_spawn) {
414 char tag[NETDATA_THREAD_TAG_MAX + 1];
@@ -421,8 +419,7 @@ static void rrdpush_sender_thread_spawn(RRDHOST *host) {
419 else
420 host->rrdpush_sender_spawn = 1;
421 }
424 -
425 - rrdhost_unlock(host);
422 + netdata_mutex_unlock(&host->sender->mutex);
423 }
424
425 int rrdpush_receiver_permission_denied(struct web_client *w) {
streaming/rrdpush.h
+3 -3
@@ -52,9 +52,9 @@ struct sender_state {
52 size_t send_attempts;
53 time_t last_sent_t;
54 size_t not_connected_loops;
55 - // metrics may be collected asynchronously
56 - // these synchronize all the threads willing the write to our sending buffer
57 - netdata_mutex_t mutex; // Guard access to buffer / build
55 + // Metrics are collected asynchronously by collector threads calling rrdset_done_push(). This can also trigger
56 + // the lazy creation of the sender thread - both cases (buffer access and thread creation) are guarded here.
57 + netdata_mutex_t mutex;
58 struct circular_buffer *buffer;
59 BUFFER *build;
60 char read_buffer[512];
streaming/sender.c
+2 -2
@@ -520,7 +520,7 @@ void execute_commands(struct sender_state *s) {
520 static void rrdpush_sender_thread_cleanup_callback(void *ptr) {
521 RRDHOST *host = (RRDHOST *)ptr;
522
523 - rrdhost_wrlock(host);
523 + netdata_mutex_lock(&host->sender->mutex);
524
525 info("STREAM %s [send]: sending thread cleans up...", host->hostname);
526
@@ -546,7 +546,7 @@ static void rrdpush_sender_thread_cleanup_callback(void *ptr) {
546
547 info("STREAM %s [send]: sending thread now exits.", host->hostname);
548
549 - rrdhost_unlock(host);
549 + netdata_mutex_unlock(&host->sender->mutex);
550 }
551
552 void sender_init(struct sender_state *s, RRDHOST *parent) {