From 8d3538e113341f586682e5a996ba5f015a22ecdd Mon Sep 17 00:00:00 2001 From: Junxuan Liao <70618504+MikeWalrus@users.noreply.github.com> Date: Sun, 19 Nov 2023 20:36:20 +0800 Subject: [PATCH] core: Destroy pipewire streams when ScreenCast sessions are closed (#130) * fix: avoid double freeing the screencopy stream * fix: avoid leaking pipewire streams * style: remove brackets around the short if --- src/portals/Screencopy.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/portals/Screencopy.cpp b/src/portals/Screencopy.cpp index 0a4c65c..ba897fd 100644 --- a/src/portals/Screencopy.cpp +++ b/src/portals/Screencopy.cpp @@ -299,7 +299,14 @@ void CScreencopyPortal::onCreateSession(sdbus::MethodCall& call) { // create objects PSESSION->session = createDBusSession(sessionHandle); - PSESSION->session->onDestroy = [PSESSION]() { PSESSION->session.release(); }; + PSESSION->session->onDestroy = [PSESSION, this]() { + if (PSESSION->sharingData.active) { + m_pPipewire->destroyStream(PSESSION); + Debug::log(LOG, "[screencopy] Stream destroyed"); + } + PSESSION->session.release(); + Debug::log(LOG, "[screencopy] Session destroyed"); + }; PSESSION->request = createDBusRequest(requestHandle); PSESSION->request->onDestroy = [PSESSION]() { PSESSION->request.release(); }; @@ -988,6 +995,11 @@ void CPipewireConnection::createStream(CScreencopyPortal::SSession* pSession) { } void CPipewireConnection::destroyStream(CScreencopyPortal::SSession* pSession) { + // Disconnecting the stream can cause reentrance to this function. + if (pSession->sharingData.active == false) + return; + pSession->sharingData.active = false; + const auto PSTREAM = streamFromSession(pSession); if (!PSTREAM || !PSTREAM->stream) @@ -1003,8 +1015,6 @@ void CPipewireConnection::destroyStream(CScreencopyPortal::SSession* pSession) { pw_stream_disconnect(PSTREAM->stream); pw_stream_destroy(PSTREAM->stream); - pSession->sharingData.active = false; - std::erase_if(m_vStreams, [&](const auto& other) { return other.get() == PSTREAM; }); } @@ -1065,7 +1075,7 @@ uint32_t CPipewireConnection::buildFormatsFor(spa_pod_builder* b[2], const spa_p paramCount = 2; params[0] = build_format(b[0], pwFromDrmFourcc(stream->pSession->sharingData.frameInfoDMA.fmt), stream->pSession->sharingData.frameInfoDMA.w, - stream->pSession->sharingData.frameInfoDMA.h, stream->pSession->sharingData.framerate, modifiers, modCount); + stream->pSession->sharingData.frameInfoDMA.h, stream->pSession->sharingData.framerate, modifiers, modCount); assert(params[0] != NULL); params[1] = build_format(b[1], pwFromDrmFourcc(stream->pSession->sharingData.frameInfoSHM.fmt), stream->pSession->sharingData.frameInfoSHM.w, stream->pSession->sharingData.frameInfoSHM.h, stream->pSession->sharingData.framerate, NULL, 0); @@ -1075,7 +1085,7 @@ uint32_t CPipewireConnection::buildFormatsFor(spa_pod_builder* b[2], const spa_p paramCount = 1; params[0] = build_format(b[0], pwFromDrmFourcc(stream->pSession->sharingData.frameInfoSHM.fmt), stream->pSession->sharingData.frameInfoSHM.w, - stream->pSession->sharingData.frameInfoSHM.h, stream->pSession->sharingData.framerate, NULL, 0); + stream->pSession->sharingData.frameInfoSHM.h, stream->pSession->sharingData.framerate, NULL, 0); } if (modifiers)