Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

videoroom: Release some references created by remote publishers #3359

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

fancycode
Copy link
Contributor

@fancycode fancycode commented Apr 23, 2024

Fixed some cases where the rtp_forwarders map was created without the destructor function. This resulted in the forwarders not being released when the publisher got destroyed.

@lminiero
Copy link
Member

I don't think that's wise: the map you see in the publisher's struct is only a shallow reference, since the actual map is stored in the publisher_stream struct, and we do have the janus_rtp_forwarder_destroy callback for the hashtable there. We risk a double free with the additions you put there I believe, or access to broken memory if the instance was destroyed already.

@fancycode
Copy link
Contributor Author

Thanks for your feedback. I had a problem where the forwarders were not released properly when my controller websocket connection was closed and the patch fixed this.

So maybe my problem must be fixed differently - I'll do some more tests and provide an update here.

@lminiero
Copy link
Member

forwarders were not released properly when my controller websocket connection was closed

I'd check if the cause is that there are publisher streams (and maybe entire publishers) whose references never get to zero causing their forwarders not to be destroyed either. Did you check by uncommenting the REFCOUNT_DEBUG define in refcount.h already? That will enable refcount debugging, which will make logs much more verbose, but will allow you to track references as they go up and down, and will print a summary of what's still there at shutdown (after you try a clean shutdown, that is, so after you closed all sessions/handles properly and shut Janus down expecting everything to be deallocated already).

@fancycode fancycode changed the title videoroom: Always destroy forwarders on hash map removal. videoroom: Release some references created by remote publishers Apr 24, 2024
Copy link
Contributor Author

@fancycode fancycode left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did some more tests with refcount debugging enabled. My initial assumption was wrong, and the problem was actually in the remote publishers that stayed active.

@@ -13421,7 +13428,7 @@ static void *janus_videoroom_remote_publisher_thread(void *user_data) {
}
g_list_free(subscribers);
/* Free streams */
g_list_free(publisher->streams);
g_list_free_full(publisher->streams, (GDestroyNotify)(janus_videoroom_publisher_stream_unref));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other places use janus_videoroom_publisher_stream_destroy but as this is also used for streams_byid, the reference would not be decreased again, resulting in a leak.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this should be a destroy, then, and the related maps both be unrefs. Besides, if that's the rationale for the list, then it should not only be fixed for remote publishers, but for all of them, since we do a simple g_list_free(participant->streams) in janus_videoroom_hangup_media_internal too. That said, we should thread carefully here, as I don't remember seeing leaks normally (all my local builds use libasan).

@@ -2433,6 +2433,8 @@ static void janus_videoroom_publisher_dereference_nodebug(janus_videoroom_publis
janus_refcount_decrease_nodebug(&p->ref);
}

static void janus_videoroom_session_destroy(janus_videoroom_session *session);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if you want the forward declaration or if one of the two functions should be moved.

Copy link
Member

@lminiero lminiero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a couple of notes inline.

@@ -2468,6 +2470,9 @@ static void janus_videoroom_publisher_destroy(janus_videoroom_publisher *p) {
}
}
janus_mutex_unlock(&p->rtp_forwarders_mutex);
/* Release dummy session of the forwarder */
if(p->session && p->session->handle == NULL)
janus_videoroom_session_destroy(p->session);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this here, and why does this mention a dummy session? This is not a function only used for dummy publishers: it's the destroy function for all publishers, and is not meant to be called directly, it's the callback for the cleanup from sessions. At the very least, this should have a p->dummy check too to ensure it's not done on regular publishers.

@@ -13421,7 +13428,7 @@ static void *janus_videoroom_remote_publisher_thread(void *user_data) {
}
g_list_free(subscribers);
/* Free streams */
g_list_free(publisher->streams);
g_list_free_full(publisher->streams, (GDestroyNotify)(janus_videoroom_publisher_stream_unref));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this should be a destroy, then, and the related maps both be unrefs. Besides, if that's the rationale for the list, then it should not only be fixed for remote publishers, but for all of them, since we do a simple g_list_free(participant->streams) in janus_videoroom_hangup_media_internal too. That said, we should thread carefully here, as I don't remember seeing leaks normally (all my local builds use libasan).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants