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) {