libmediasoupclient device.Load crashes

Hello,

I experience a crash with the device.Load function call from libmediasoupclient C++ library.

It happened first with the mediasoup-broadcaster-demo, but I’ve tried to isolate the call in a smaller program and the behaviour is the same.

	std::ifstream f("router_caps.json");
	json routerRtpCapabilities = json::parse(f);

	mediasoupclient::Initialize();
	device.Load(routerRtpCapabilities);

Router capabilities json:

{
    "codecs": [
        {
            "kind": "audio",
            "mimeType": "audio/opus",
            "clockRate": 48000,
            "channels": 2,
            "rtcpFeedback": [
                {
                    "type": "nack",
                    "parameter": ""
                },
                {
                    "type": "transport-cc",
                    "parameter": ""
                }
            ],
            "parameters": {},
            "preferredPayloadType": 100
        },
        {
            "kind": "video",
            "mimeType": "video/H264",
            "clockRate": 90000,
            "parameters": {
                "level-asymmetry-allowed": 1,
                "x-google-start-bitrate": 1000
            },
            "rtcpFeedback": [
                {
                    "type": "nack",
                    "parameter": ""
                },
                {
                    "type": "nack",
                    "parameter": "pli"
                },
                {
                    "type": "ccm",
                    "parameter": "fir"
                },
                {
                    "type": "goog-remb",
                    "parameter": ""
                },
                {
                    "type": "transport-cc",
                    "parameter": ""
                }
            ],
            "preferredPayloadType": 101
        },
        {
            "kind": "video",
            "mimeType": "video/rtx",
            "preferredPayloadType": 102,
            "clockRate": 90000,
            "parameters": {
                "apt": 101
            },
            "rtcpFeedback": []
        }
    ],
    "headerExtensions": [
        {
            "kind": "audio",
            "uri": "urn:ietf:params:rtp-hdrext:sdes:mid",
            "preferredId": 1,
            "preferredEncrypt": false,
            "direction": "sendrecv"
        },
        {
            "kind": "video",
            "uri": "urn:ietf:params:rtp-hdrext:sdes:mid",
            "preferredId": 1,
            "preferredEncrypt": false,
            "direction": "sendrecv"
        },
        {
            "kind": "video",
            "uri": "urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id",
            "preferredId": 2,
            "preferredEncrypt": false,
            "direction": "recvonly"
        },
        {
            "kind": "video",
            "uri": "urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id",
            "preferredId": 3,
            "preferredEncrypt": false,
            "direction": "recvonly"
        },
        {
            "kind": "audio",
            "uri": "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time",
            "preferredId": 4,
            "preferredEncrypt": false,
            "direction": "sendrecv"
        },
        {
            "kind": "video",
            "uri": "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time",
            "preferredId": 4,
            "preferredEncrypt": false,
            "direction": "sendrecv"
        },
        {
            "kind": "audio",
            "uri": "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01",
            "preferredId": 5,
            "preferredEncrypt": false,
            "direction": "recvonly"
        },
        {
            "kind": "video",
            "uri": "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01",
            "preferredId": 5,
            "preferredEncrypt": false,
            "direction": "sendrecv"
        },
        {
            "kind": "video",
            "uri": "http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07",
            "preferredId": 6,
            "preferredEncrypt": false,
            "direction": "sendrecv"
        },
        {
            "kind": "video",
            "uri": "urn:ietf:params:rtp-hdrext:framemarking",
            "preferredId": 7,
            "preferredEncrypt": false,
            "direction": "sendrecv"
        },
        {
            "kind": "audio",
            "uri": "urn:ietf:params:rtp-hdrext:ssrc-audio-level",
            "preferredId": 10,
            "preferredEncrypt": false,
            "direction": "sendrecv"
        },
        {
            "kind": "video",
            "uri": "urn:3gpp:video-orientation",
            "preferredId": 11,
            "preferredEncrypt": false,
            "direction": "sendrecv"
        },
        {
            "kind": "video",
            "uri": "urn:ietf:params:rtp-hdrext:toffset",
            "preferredId": 12,
            "preferredEncrypt": false,
            "direction": "sendrecv"
        },
        {
            "kind": "audio",
            "uri": "http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time",
            "preferredId": 13,
            "preferredEncrypt": false,
            "direction": "sendrecv"
        },
        {
            "kind": "video",
            "uri": "http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time",
            "preferredId": 13,
            "preferredEncrypt": false,
            "direction": "sendrecv"
        }
    ]
}

Here the output with WebRTC Log on:

(audio_processing_impl.cc:281): Injected APM submodules:
Echo control factory: 0                                                                                                                                     Echo detector: 0
Capture analyzer: 0
Capture post processor: 0                                                                                                                                   Render pre processor: 0
(audio_processing_impl.cc:290): Denormal disabler: unsupported
(webrtc_voice_engine.cc:314): WebRtcVoiceEngine::WebRtcVoiceEngine
(webrtc_voice_engine.cc:336): WebRtcVoiceEngine::Init
(webrtc_voice_engine.cc:432): WebRtcVoiceEngine::ApplyOptions: AudioOptions {aec: 1, agc: 1, ns: 1, hf: 1, swap: 0, audio_jitter_buffer_max_packets: 200, audio_jitter_buffer_fast_accelerate: 0, audio_jitter_buffer_min_delay_ms: 0, audio_jitter_buffer_enable_rtx_handling: 0, typing: 1, experimental_agc: 0, experimental_ns: 0, residual_echo_detector: 1, }
(webrtc_voice_engine.cc:541): Stereo swapping enabled? 0
(webrtc_voice_engine.cc:546): NetEq capacity is 200
(webrtc_voice_engine.cc:552): NetEq fast mode? 0
(webrtc_voice_engine.cc:558): NetEq minimum delay is 0
(webrtc_voice_engine.cc:564): NetEq handle reordered packets? 0
(webrtc_voice_engine.cc:584): Experimental ns is enabled? 0
(webrtc_voice_engine.cc:635): NS set to 1
(webrtc_voice_engine.cc:639): Typing detection is enabled? 1
(audio_processing_impl.cc:539): AudioProcessing::ApplyConfig: AudioProcessing::Config{ pipeline: { maximum_internal_processing_rate: 48000, multi_channel_render: 0, multi_channel_capture: 0 }, pre_amplifier: { enabled: 0, fixed_gain_factor: 1 },capture_level_adjustment: { enabled: 0, pre_gain_factor: 1, post_gain_factor: 1, analog_mic_gain_emulation: { enabled: 0, initial_level: 255 }}, high_pass_filter: { enabled: 1 }, echo_canceller: { enabled: 1, mobile_mode: 0, enforce_high_pass_filtering: 1 }, noise_suppression: { enabled: 1, level: High }, transient_suppression: { enabled: 0 }, voice_detection: { enabled: 1 }, gain_controller1: { enabled: 1, mode: AdaptiveAnalog, target_level_dbfs: 3, compression_gain_db: 9, enable_limiter: 1, analog_level_minimum: 0, analog_level_maximum: 255, analog_gain_controller { enabled: 1, startup_min_volume: 0, clipped_level_min: 70, enable_digital_adaptive: 1, clipped_level_step: 15, clipped_ratio_threshold: 0.1, clipped_wait_frames: 300, clipping_predictor:  { enabled: 0, mode: 0, window_length: 5, reference_window_length: 5, reference_window_delay: 5, clipping_threshold: -1, crest_factor_margin: 3 }}}, gain_controller2: { enabled: 0, fixed_digital: { gain_db: 0 }, adaptive_digital: { enabled: 0, dry_run: 0, noise_estimator: NoiseFloor, vad_reset_period_ms: 1500, adjacent_speech_frames_threshold: 12, max_gain_change_db_per_second: 3, max_output_noise_level_dbfs: -50, sse2_allowed: 1, avx2_allowed: 1, neon_allowed: 1}}, residual_echo_detector: { enabled: 1 }, level_estimation: { enabled: 0 }}
(transparent_mode.cc:239): AEC3 Transparent Mode: Legacy
(echo_canceller3.cc:749): AEC3 created with sample rate: 16000 Hz, num render channels: 1, num capture channels: 1
(clipping_predictor.cc:357): [agc] Clipping prediction disabled.
(agc_manager_direct.cc:69): [agc] GetMinMicLevel
(agc_manager_direct.cc:73): [agc] Using default min mic level: 12
(rtc_event_log_impl.cc:43): Creating legacy encoder for RTC event log.
(peer_connection_factory.cc:338): Using default network controller factory
(bitrate_prober.cc:72): Bandwidth probing enabled, set to inactive
(cpu_info.cc:53): Available number of cores: 8
(aimd_rate_control.cc:112): Using aimd rate control with back off factor 0.85
(remote_bitrate_estimator_single_stream.cc:71): RemoteBitrateEstimatorSingleStream: Instantiating.
(remote_estimator_proxy.cc:47): Maximum interval between transport feedback RTCP messages (ms): 250
(openssl_key_pair.cc:38): Making key pair
(peer_connection.cc:1034): Adding audio transceiver in response to a call to AddTransceiver.
(openssl_key_pair.cc:91): Returning key pair
(boringssl_certificate.cc:187): Making certificate for WebRTC
(peer_connection.cc:1034): Adding video transceiver in response to a call to AddTransceiver.
(boringssl_certificate.cc:243): Returning certificate
(used_ids.h:55): Duplicate id found. Reassigning from 102 to 127
(used_ids.h:55): Duplicate id found. Reassigning from 104 to 125
(used_ids.h:55): Duplicate id found. Reassigning from 106 to 124
(used_ids.h:55): Duplicate id found. Reassigning from 110 to 123
(used_ids.h:55): Duplicate id found. Reassigning from 112 to 122
(used_ids.h:55): Duplicate id found. Reassigning from 102 to 121
(used_ids.h:55): Duplicate id found. Reassigning from 103 to 120
(used_ids.h:55): Duplicate id found. Reassigning from 105 to 119
(used_ids.h:55): Duplicate id found. Reassigning from 111 to 118
(used_ids.h:55): Duplicate id found. Reassigning from 1 to 14
(used_ids.h:55): Duplicate id found. Reassigning from 3 to 13
(used_ids.h:55): Duplicate id found. Reassigning from 5 to 12
(used_ids.h:55): Duplicate id found. Reassigning from 6 to 11
(peer_connection.cc:545): Session: 7948451668743586024 is destroyed.
(paced_sender.cc:187): ProcessThreadAttached 0x0
(dtmf_sender.cc:240): The Dtmf provider is deleted. Clear the sending queue.
(webrtc_voice_engine.cc:322): WebRtcVoiceEngine::~WebRtcVoiceEngine
[1]    34666 trace trap

Trying to debug a bit, it seems the crash is triggered by the call

this->pc = this->peerConnectionFactory->CreatePeerConnection(config, nullptr, nullptr, privateListener);

in PeerConnection.cpp:110

I used WebRTC m94 branch, gcc 10.5.0. Tested on multiple Linux machines with the same output.

I might be doing something very wrong, but any hint on where to look to debug further would be extermely appreciated :flushed:

“Solved”.
Recompiled everything with gcc 9.5.0 and it works.

I tried to go further with the debugging process to understand why compiling with gcc 10.5.0 leads to crashes.
The Minimum Reproducible Example I found is the following:

#include "mediasoupclient.hpp"
#include <cstdlib>
#include <iostream>
#include <string>
#include <fstream>

using json = nlohmann::json;

#include "pc/test/fake_periodic_video_track_source.h"

// Video track creation.
rtc::scoped_refptr<webrtc::VideoTrackInterface> createVideoTrack(const std::string& /*label*/)
{
	auto* videoTrackSource =
	  new rtc::RefCountedObject<webrtc::FakePeriodicVideoTrackSource>(false /* remote */);

	return nullptr;
}


int main(int /*argc*/, char* /*argv*/[])
{
    mediasoupclient::Device device;
	rtc::LogMessage::LogToDebug(rtc::LoggingSeverity::LS_INFO);

	auto logLevel = mediasoupclient::Logger::LogLevel::LOG_DEBUG;
	mediasoupclient::Logger::SetLogLevel(logLevel);
	mediasoupclient::Logger::SetDefaultHandler();

	std::ifstream f("router_caps.json");
	json routerRtpCapabilities = json::parse(f);

	mediasoupclient::Initialize();

	device.Load(routerRtpCapabilities);

	std::cout << "[INFO] dev loaded!\n" << std::endl;
    std::cin.ignore();

    return 0;
}

just having the line

	auto* videoTrackSource =
	  new rtc::RefCountedObject<webrtc::FakePeriodicVideoTrackSource>(false /* remote */);

leads to a crash in the webrtc signaling thread even if the function is not called at all.
If that line is removed it works fine. :confused:

Thread 3 "signaling_threa" received signal SIGTRAP, Trace/breakpoint trap.
[Switching to Thread 0x7ffff7234640 (LWP 233473)]
0x00005555559ad46c in base::internal::(anonymous namespace)::FreelistCorruptionDetected(unsigned long) ()
(gdb) bt
#0  0x00005555559ad46c in base::internal::(anonymous namespace)::FreelistCorruptionDetected(unsigned long) ()
#1  0x00005555559ad4e0 in base::internal::PartitionFreelistEntry::CheckFreeList(unsigned long) const ()
#2  0x00005555559ae7cd in base::internal::ThreadCache::PurgeInternal() ()
#3  0x00005555559aee94 in base::internal::ThreadCache::Delete(void*) ()
#4  0x00007ffff7acc711 in __GI___nptl_deallocate_tsd () at ./nptl/nptl_deallocate_tsd.c:73
#5  __GI___nptl_deallocate_tsd () at ./nptl/nptl_deallocate_tsd.c:22
#6  0x00007ffff7acf9ca in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:453
#7  0x00007ffff7b61a00 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81

It seems the bug is somehow dependent on libwebrtc and not on libmediasoupclient, so I don’t know if it might make sense to add the upper bound limit to the documentation for compiling libmediasoupclient since it says

gcc and g++ >= 4.9