From 44a153c05ee70699f06256f456292f6c47206f9d Mon Sep 17 00:00:00 2001 From: Dylan Mikus Date: Thu, 14 Jul 2016 16:16:50 +0000 Subject: [PATCH] Made interactions to recording metadata threadsafe Updating, freeing, and writing the recording metadata is now threadsafe. This is in regards to the metadata that we receive from the `rtpengine_offer` or `rtpengine_answer` commands, not the `meta_fp` file. We can simply use the `call->master_lock` variable for protecting updates to the recording metadata. We had to move the metadata handling code in call_interfaces.c up into the master_lock guarded section. The code in "recording.c:meta_finish_file" is called with master_lock protection already. --- daemon/call_interfaces.c | 41 ++++++++++++++++++++-------------------- daemon/recording.c | 2 ++ 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index f1eda99cb..fd7c9a83f 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -720,26 +720,6 @@ static const char *call_offer_answer_ng(bencode_item_t *input, struct callmaster if (!ret) ret = sdp_replace(chopper, &parsed, monologue->active_dialogue, &flags); - rwlock_unlock_w(&call->master_lock); - redis_update(call, m->conf.redis_write); - obj_put(call); - - gettimeofday(&(monologue->started), NULL); - - errstr = "Error rewriting SDP"; - - if (ret == ERROR_NO_FREE_PORTS || ret == ERROR_NO_FREE_LOGS) { - ilog(LOG_ERR, "Destroying call"); - call_destroy(call); - } - - if (ret) - goto out; - - bencode_dictionary_add_iovec(output, "sdp", &g_array_index(chopper->iov, struct iovec, 0), - chopper->iov_num, chopper->str_len); - bencode_dictionary_add_string(output, "result", "ok"); - struct recording *recording = call->recording; if (call->record_call && recording != NULL && recording->meta_fp != NULL) { struct iovec *iov = &g_array_index(chopper->iov, struct iovec, 0); @@ -751,6 +731,7 @@ static const char *call_offer_answer_ng(bencode_item_t *input, struct callmaster if (metadata.len > 0 && call->recording != NULL) { if (call->recording->metadata != NULL) { free(call->recording->metadata); + call->recording->metadata = NULL; } call->recording->metadata = str_dup(&metadata); } @@ -760,6 +741,26 @@ static const char *call_offer_answer_ng(bencode_item_t *input, struct callmaster bencode_list_add_string(recordings, recording_path); } + rwlock_unlock_w(&call->master_lock); + redis_update(call, m->conf.redis_write); + obj_put(call); + + gettimeofday(&(monologue->started), NULL); + + errstr = "Error rewriting SDP"; + + if (ret == ERROR_NO_FREE_PORTS || ret == ERROR_NO_FREE_LOGS) { + ilog(LOG_ERR, "Destroying call"); + call_destroy(call); + } + + if (ret) + goto out; + + bencode_dictionary_add_iovec(output, "sdp", &g_array_index(chopper->iov, struct iovec, 0), + chopper->iov_num, chopper->str_len); + bencode_dictionary_add_string(output, "result", "ok"); + errstr = NULL; out: sdp_free(&parsed); diff --git a/daemon/recording.c b/daemon/recording.c index f7df890e3..d57b91b4c 100644 --- a/daemon/recording.c +++ b/daemon/recording.c @@ -231,6 +231,7 @@ ssize_t meta_write_sdp(FILE *meta_fp, struct iovec *sdp_iov, int iovcnt, * Returns non-zero for failure. */ int meta_finish_file(struct call *call) { + // This should usually be called from a place that has the call->master_lock struct recording *recording = call->recording; int return_code = 0; @@ -251,6 +252,7 @@ int meta_finish_file(struct call *call) { // Print metadata fprintf(recording->meta_fp, "\n\n%s\n", recording->metadata->s); free(recording->metadata); + recording->metadata = NULL; fclose(recording->meta_fp); // Get the filename (in between its directory and the file extension)