Kodi crashes when a PVR stream is stopped via remote app (unhandled bad_variant_access exception)
Bug report
Describe the bug
Here is a clear and concise description of what the problem is:
Kodi crashes when playing a PVR stream via "inputstream.ffmpegdirect" plugin and using remote control app, Yatse, to start and stop the stream. Playing starts normally. Stopping results in crash. Kodi does not crash when playing files from the disk. Also it does not crash when playing PVR streams via "inputstream.adaptive" plugin. I have identified crash place and suggested a patch to fix, see below.
Expected Behavior
Here is a clear and concise description of what was expected to happen:
Kodi should not crash when stopping a PVR stream with remote control app.
Actual Behavior
Kodi crashes due to unhandled bad_variant_access exception.
Possible Fix
The crash happens when remote app makes RPC call without parameters, but webserver tries to parse the empty parameters string eventually calling the CVariant.size() in a Null constant. Catching this exception fixes the problem.
--- a/xbmc/interfaces/json-rpc/JSONServiceDescription.cpp.bak 2025-01-15 17:14:15.000000000 -0500
+++ b/xbmc/interfaces/json-rpc/JSONServiceDescription.cpp 2025-03-23 19:12:50.625726613 -0400
@@ -1387,13 +1387,15 @@
}
// Check if there were unnecessary parameters
+ try {
if (handled < requestParameters.size())
{
errorData["message"] = "Too many parameters";
outputParameters = errorData;
return InvalidParams;
}
-
+ } catch (std::bad_variant_access e) {
+ }
return OK;
}
else
To Reproduce
Steps to reproduce the behavior:
- Start playing a PVR stream via iptvsimple plugin.
- Press Stop button in Yatse.
Debuglog
The debuglog can be found here: https://pastebin.com/Z4iq51Lk
Screenshots
Here are some links or screenshots to help explain the problem:
Additional context or screenshots (if appropriate)
Here is some additional context or explanation that might help:
Your Environment
Used Operating system:
-
[ ] Android
-
[ ] iOS
-
[ ] tvOS
-
[X] Linux
-
[ ] macOS
-
[ ] Windows
-
[ ] Windows UWP
-
Operating system version/name:
-
Kodi version: 21.2 Omega
note: Once the issue is made we require you to update it with new information or Kodi versions should that be required. Team Kodi will consider your problem report however, we will not make any promises the problem will be solved.
Catching this exception fixes the problem.
Although this works, I don't think his is the right/best fix approach.
The crash happens when remote app makes RPC call without parameters
In addition to make Kodi survive this scenario, Yatse should be fixed to not send invalid RPC calls.
I have found a similar issue when starting a PVR stream play via inputstream.adaptive after another stream was played via inputstream.ffmpegdirect. Only this time bad_variant_access is thrown from CVariant.asString().
I am still trying to figure out a reliable way to reproduce this issue. But the fix could probably be similar to the one that fixes CVariant.size() on null constant.
The problem is clearly that the CVariant::ConstNullVariant contains an empty std::variant. A std::variant being empty can happen in some situations, see https://en.cppreference.com/w/cpp/utility/variant/valueless_by_exception.
But: Non of that should affect the CVariant::ConstNullVariant because it should be immutable (e.g. operator= is a null-op, etc.). The problem is that we messed this up in at least one place, CVariant::swap(). This allows to change the CVariant::ConstNullVariant to any type and it can be modified arbitrarily afterwards.
https://github.com/xbmc/xbmc/blob/71734296782076b8b5971d311efcb164738cf05c/xbmc/utils/Variant.cpp#L600-L603
I'll PR a fix for that and hopefully this also solves this issue 🙂
@David-EIPI, are you able to build Kodi yourself to test if xbmc/xbmc#26581 fixes the issue?
Yes, I have just built Kodi with https://github.com/xbmc/xbmc/pull/26581. The crash still happens, exception is thrown at the same line in CVariant.size(). I can attach the log if needed, but it is essentially the same, only line number has changed from Variant.cpp:663 to Variant.cpp:666.
Would have been too easy... Please provide the stack trace and Kodi log output.
Here it is. https://pastebin.com/FcAutYGT (updated link)
From the new log I unfortunately can't say if CVariant::ConstNullVariant being empty has been fixed or not. And therefore it's not clear if that has been the original issue or was just something that we spotted by accident.
Looks like the new build has worse debug information than the original one. If you make a debug build we should get more insight.
Sorry, forgot to add full dump options. Here is the full log https://pastebin.com/FcAutYGT
Found it!
The problem is with inputstream.ffmpegdirect, it also has a CVariant class in its global name space which differs from the Kodi version. When the inputstream.ffmpegdirect shared object is loaded the initializer for their global static CVariant::ConstNullVariant is executed, but because the symbol already exists in the Kodi binary it overwrites that instance with an incompatible binary representation.
The fix is to move the CVariant in inputstream.ffmpegdirect into its own namespace.
That is some amazing insight, neo1973!
I have just tested it. Moved addon's CVariant into existing namespace ffmpegdirect, because many source files already use it = less edits.
Rebuilt and so far no more crashes! Thanks a lot!
Please feel free to the PR the change the Piers branch of ffmpegdirect.
Once it’s there so can also bring it into Omega.