PipeWire: call pw_deinit() only when running against PipeWire 3.49+ pw_deinit() was not reetrant in old PipeWire versions and it only got fixed with PipeWire 3.49. This is causing a crash for old Ubuntu 22.04 with PipeWire 3.48 when sharing screen multiple times. This also moves all the PipeWire version parsing logic to pipewire_utils from screencast_utils as it makes more sense and is used from there now. Bug: chromium:490340738 Change-Id: I62ec7adfcba040b4ab99bf535b3f16b5e4b27c1a Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/455180 Commit-Queue: Jan Grulich <grulja@gmail.com> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Reviewed-by: Andreas Pehrson <apehrson@mozilla.com> Reviewed-by: Alexander Cooper <alcooper@chromium.org> Reviewed-by: Mark Foltz <mfoltz@chromium.org> Cr-Commit-Position: refs/heads/main@{#47100}
diff --git a/modules/desktop_capture/linux/wayland/screencast_stream_utils.cc b/modules/desktop_capture/linux/wayland/screencast_stream_utils.cc index 7e4ad53..a590cac 100644 --- a/modules/desktop_capture/linux/wayland/screencast_stream_utils.cc +++ b/modules/desktop_capture/linux/wayland/screencast_stream_utils.cc
@@ -26,10 +26,7 @@ #include <tuple> #include <vector> -#include "absl/strings/string_view.h" #include "modules/desktop_capture/linux/wayland/egl_dmabuf.h" -#include "rtc_base/string_encode.h" -#include "rtc_base/string_to_number.h" #if !PW_CHECK_VERSION(0, 3, 29) #define SPA_POD_PROP_FLAG_MANDATORY (1u << 3) @@ -44,50 +41,6 @@ SPA_VIDEO_FORMAT_BGRA, SPA_VIDEO_FORMAT_RGBA, SPA_VIDEO_FORMAT_BGRx, SPA_VIDEO_FORMAT_RGBx}; -PipeWireVersion PipeWireVersion::Parse(const absl::string_view& version) { - std::vector<absl::string_view> parsed_version = split(version, '.'); - - if (parsed_version.size() != 3) { - return {}; - } - - std::optional<int> major = StringToNumber<int>(parsed_version.at(0)); - std::optional<int> minor = StringToNumber<int>(parsed_version.at(1)); - std::optional<int> micro = StringToNumber<int>(parsed_version.at(2)); - - // Return invalid version if we failed to parse it - if (!major || !minor || !micro) { - return {}; - } - - return {.major = major.value(), - .minor = minor.value(), - .micro = micro.value(), - .full_version = std::string(version)}; -} - -bool PipeWireVersion::operator>=(const PipeWireVersion& other) { - if (!major && !minor && !micro) { - return false; - } - - return std::tie(major, minor, micro) >= - std::tie(other.major, other.minor, other.micro); -} - -bool PipeWireVersion::operator<=(const PipeWireVersion& other) { - if (!major && !minor && !micro) { - return false; - } - - return std::tie(major, minor, micro) <= - std::tie(other.major, other.minor, other.micro); -} - -absl::string_view PipeWireVersion::ToStringView() const { - return full_version; -} - void BuildBaseFormatParams(spa_pod_builder* builder, uint32_t format, const struct spa_rectangle* resolution,
diff --git a/modules/desktop_capture/linux/wayland/screencast_stream_utils.h b/modules/desktop_capture/linux/wayland/screencast_stream_utils.h index 27d58d2..4e3492e 100644 --- a/modules/desktop_capture/linux/wayland/screencast_stream_utils.h +++ b/modules/desktop_capture/linux/wayland/screencast_stream_utils.h
@@ -15,8 +15,6 @@ #include <vector> -#include "absl/strings/string_view.h" - struct spa_pod; struct spa_pod_builder; struct spa_rectangle; @@ -26,22 +24,6 @@ class EglDrmDevice; -struct PipeWireVersion { - static PipeWireVersion Parse(const absl::string_view& version); - - // Returns whether current version is newer or same as required version - bool operator>=(const PipeWireVersion& other); - // Returns whether current version is older or same as required version - bool operator<=(const PipeWireVersion& other); - - absl::string_view ToStringView() const; - - int major = 0; - int minor = 0; - int micro = 0; - std::string full_version; -}; - // Builds base video format parameters. The format parameter consists of: // - SPA_FORMAT_mediaType with SPA_MEDIA_TYPE_video // - SPA_FORMAT_mediaSubtype with SPA_MEDIA_SUBTYPE_raw
diff --git a/modules/portal/pipewire_utils.cc b/modules/portal/pipewire_utils.cc index 91a2ae6..850726c 100644 --- a/modules/portal/pipewire_utils.cc +++ b/modules/portal/pipewire_utils.cc
@@ -12,7 +12,15 @@ #include <pipewire/pipewire.h> +#include <optional> +#include <string> +#include <string_view> +#include <tuple> +#include <vector> + #include "rtc_base/sanitizer.h" +#include "rtc_base/string_encode.h" +#include "rtc_base/string_to_number.h" #if defined(WEBRTC_DLOPEN_PIPEWIRE) #include "modules/portal/pipewire_stubs.h" @@ -20,6 +28,45 @@ namespace webrtc { +constexpr PipeWireVersion kReentrantDeinitMinVersion = {.major = 0, + .minor = 3, + .micro = 49}; + +PipeWireVersion PipeWireVersion::Parse(const std::string_view& version) { + std::vector<std::string_view> parsed_version = split(version, '.'); + + if (parsed_version.size() != 3) { + return {}; + } + + std::optional<int> major = StringToNumber<int>(parsed_version.at(0)); + std::optional<int> minor = StringToNumber<int>(parsed_version.at(1)); + std::optional<int> micro = StringToNumber<int>(parsed_version.at(2)); + + // Return invalid version if we failed to parse it + if (!major || !minor || !micro) { + return {}; + } + + return {.major = major.value(), + .minor = minor.value(), + .micro = micro.value(), + .full_version = std::string(version)}; +} + +bool PipeWireVersion::operator>=(const PipeWireVersion& other) { + if (!major && !minor && !micro) { + return false; + } + + return std::tie(major, minor, micro) >= + std::tie(other.major, other.minor, other.micro); +} + +std::string_view PipeWireVersion::ToStringView() const { + return full_version; +} + RTC_NO_SANITIZE("cfi-icall") bool InitializePipeWire() { #if defined(WEBRTC_DLOPEN_PIPEWIRE) @@ -57,7 +104,11 @@ RTC_NO_SANITIZE("cfi-icall") PipeWireInitializer::~PipeWireInitializer() { - pw_deinit(); + PipeWireVersion pw_client_version = + PipeWireVersion::Parse(pw_get_library_version()); + if (pw_client_version >= kReentrantDeinitMinVersion) { + pw_deinit(); + } } } // namespace webrtc
diff --git a/modules/portal/pipewire_utils.h b/modules/portal/pipewire_utils.h index c22f296..d0734c1 100644 --- a/modules/portal/pipewire_utils.h +++ b/modules/portal/pipewire_utils.h
@@ -17,6 +17,8 @@ #include <cerrno> #include <cstdint> +#include <string> +#include <string_view> // static struct dma_buf_sync { @@ -34,6 +36,20 @@ constexpr int kInvalidPipeWireFd = -1; +struct PipeWireVersion { + static PipeWireVersion Parse(const std::string_view& version); + + // Returns whether current version is newer or same as required version + bool operator>=(const PipeWireVersion& other); + + std::string_view ToStringView() const; + + int major = 0; + int minor = 0; + int micro = 0; + std::string full_version; +}; + // Prepare PipeWire so that it is ready to be used. If it needs to be dlopen'd // this will do so. Note that this does not guarantee a PipeWire server is // running nor does it establish a connection to one.