-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
SeqManager<T>::SeqLowerThan() crashes when used as compare function in abseil set or map (only in debug mode) #1366
Comments
@shaymagsumov, that the provider snippet generate the crash? |
I mean that snippet reproduces the same crash as in NackGenerator. Same assert is failing in absl's btree container. Assert code in file
|
I feel that this may indeed happen due to |
template<typename T, uint8_t N>
bool SeqManager<T, N>::SeqLowerThan::operator()(T lhs, T rhs) const
{
return ((rhs > lhs) && (rhs - lhs <= MaxValue / 2)) ||
((lhs > rhs) && (lhs - rhs > MaxValue / 2));
}
template<typename T, uint8_t N>
bool SeqManager<T, N>::IsSeqLowerThan(T lhs, T rhs)
{
return isSeqLowerThan(lhs, rhs);
}
So // Compare a: 10000 with b: 40000:
SeqManager<16, 0>::IsSeqLowerThan(10000, 40000);
// => true
// Compare b: 40000 with c: 60000:
SeqManager<16, 0>::IsSeqLowerThan(40000, 60000);
// => true
// Compare a: 10000 with c: 60000:
SeqManager<16, 0>::IsSeqLowerThan(10000, 60000);
// => false <-------------- UPPPPPS UPPPPS NOTE: I DO KNOW that this is the expected result given how |
Said that, I've added these tests in SCENARIO("ISSUE 1366: https://github.com/versatica/mediasoup/issues/1366")
{
SECTION("absl::btree_set")
{
REQUIRE(RTC::SeqManager<uint16_t>::IsSeqLowerThan(10000, 40000) == true);
REQUIRE(RTC::SeqManager<uint16_t>::IsSeqLowerThan(40000, 60000) == true);
REQUIRE(RTC::SeqManager<uint16_t>::IsSeqLowerThan(10000, 60000) == false);
}
SECTION("std::set")
{
std::set<uint16_t, RTC::SeqManager<uint16_t>::SeqLowerThan> recoveredList;
recoveredList.insert(10000);
recoveredList.insert(40000);
recoveredList.insert(60000);
REQUIRE(recoveredList.size() == 3);
}
SECTION("absl::btree_set")
{
absl::btree_set<uint16_t, RTC::SeqManager<uint16_t>::SeqLowerThan> recoveredList;
recoveredList.insert(10000);
recoveredList.insert(40000);
recoveredList.insert(60000);
REQUIRE(recoveredList.size() == 3);
}
} |
May be it will crash, when you change |
No no, you said that this exact code should crash: absl::btree_set<uint16_t, SeqManager<uint16_t>::SeqLowerThan> recoveredList;
recoveredList.insert(10000);
recoveredList.insert(40000);
recoveredList.insert(60000); This is not about |
Yes, you're right, my bad |
Then how is it possible that it doesn't crash for me and it crashes for you? We are supposed to use the very same version of abseil. |
Just added this section to the end of TestNackGenerator.cpp:
Result:
|
I think i got it. I build and run it in debug mode, so assert is not optimized away and crashes. |
The thing is: we DONT want to honor that "transitivity, i.e. comp(a,b) && comp(b,c) -> comp(a,c)". Is this a abseil thing? If so we should use |
Looks like std::set imposes same requirements on compare function if comp(a, b) == true and comp(b, c) == true then comp(a, c) == true. |
No idea what to do here. We do want current behavior. In fact we want this: REQUIRE(RTC::SeqManager<uint16_t>::IsSeqLowerThan(10000, 40000) == true);
REQUIRE(RTC::SeqManager<uint16_t>::IsSeqLowerThan(40000, 60000) == true);
REQUIRE(RTC::SeqManager<uint16_t>::IsSeqLowerThan(10000, 60000) == false); However this desired behavior violates "transitivity, i.e. comp(a,b) && comp(b,c) -> comp(a,c)". |
So interestingly, in debug mode only abseil aborts: SCENARIO("ISSUE 1366: https://github.com/versatica/mediasoup/issues/1366")
{
SECTION("absl::btree_set")
{
REQUIRE(RTC::SeqManager<uint16_t>::IsSeqLowerThan(10000, 40000) == true);
REQUIRE(RTC::SeqManager<uint16_t>::IsSeqLowerThan(40000, 60000) == true);
REQUIRE(RTC::SeqManager<uint16_t>::IsSeqLowerThan(10000, 60000) == false);
}
SECTION("std::set")
{
std::set<uint16_t, RTC::SeqManager<uint16_t>::SeqLowerThan> recoveredList;
recoveredList.insert(10000);
recoveredList.insert(40000);
recoveredList.insert(60000);
REQUIRE(recoveredList.size() == 3);
}
SECTION("absl::btree_set")
{
absl::btree_set<uint16_t, RTC::SeqManager<uint16_t>::SeqLowerThan> recoveredList;
recoveredList.insert(10000);
recoveredList.insert(40000);
recoveredList.insert(60000);
REQUIRE(recoveredList.size() == 3);
}
}
|
Let's see how |
Fixes #1366 ### Details - As demonstrated in temporal PR #1368, standard C++ STD containers do not throw (even in debug mode) when using `Compare` functions in maps/sets that do not honor transitivity, i.e. `comp(a,b) && comp(b,c) -> comp(a,c)`. - So let's not use abseil containers in those cases. ### Bonus tracks - Dupicate CI actions in debug mode. - Make mediasoup Rust building honor `MEDIASOUP_BUILDTYPE` env variable if given. - Fix an amazing bug in `AudioLevelObserver.cpp` which failed to compile because it uses a `absl::btree_multimap` without including the `absl/container/btree_map.h` header (it didn't fail before due to some absl header included by yet anothe included file, etc).
PR fixing the issue done: #1369 |
Well, WebRTC uses |
It may use |
What i mean is when receiving packet, unwarp |
What is |
@penguinol this issue is closed because I've merged a PR that, among other things, fixes this. However we can keep discussing your suggestion. |
Yes, |
And what haI've created a separate task for this: #1370 |
This happens very rarely. I can't reproduce it nor attach core dump for now. But i have located it at:
https://github.com/versatica/mediasoup/blob/v3/worker/src/RTC/NackGenerator.cpp#L119
I can repoduce similar crash separatedly from worker in this sample:
The text was updated successfully, but these errors were encountered: