[Bug Report] Crash on loading JSON due to LTO (Link Time Optimisations)
Description of Bug
I run Pop!_OS 21.04 on a Ryzen 3800X with the Gigabyte X570 Aorus Master board, together with a number of RGB lighting enabled peripherals such as the Corsair H150i, Corsair Commander Pro and Logitech G502 mouse.
Ever since upgrading Pop!_OS from 20.10, I have been unable to launch OpenRGB (built from source). The application crashes when loading its JSON configuration, triggered somewhere deep inside the nlohmann/json library. A backtrace is given further below.
While the template-heavy JSON library is a challenge to read at times, I understood the relevant bits enough but could not see anything obviously wrong.
After some experimentation, I'm inclined to believe the problem is due to a combination of the GCC 10.3.0 compiler shipped with the distribution and the use of LTO. OpenRGB builds with the distro provided GCC 9, GCC 11 and Clang 12 appear to be okay. GCC 10 also appears to work fine with LTO disabled.
I guess this issue should probably be filed with Pop!_OS but I thought it a good idea to sound out the problem here where OpenRGB users and packagers tend to look first.
Steps to reproduce:
- Build OpenRGB from source using GCC 10.3.0 on Pop!_OS 21.04.
- Remove all existing OpenRGB configuration with
rm -rf ~/.config/OpenRGB. - Launch OpenRGB once to create configuration and quit immediately.
- Launch OpenRGB a second time to observe crash.
Backtrace:
Reading symbols from ./openrgb...
(gdb) run
Starting program: /home/kaixiong/Documents/sources/OpenRGB/openrgb
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Program received signal SIGSEGV, Segmentation fault.
nlohmann::detail::input_stream_adapter::get_character (this=0x7fffffffd6f8) at dependencies/hueplusplus-1.0.0/include/json/json.hpp:3978
3978 auto res = sb.sbumpc();
(gdb) bt
#0 nlohmann::detail::input_stream_adapter::get_character (this=0x7fffffffd6f8) at dependencies/hueplusplus-1.0.0/include/json/json.hpp:3978
#1 nlohmann::detail::lexer<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> > >, nlohmann::detail::input_stream_adapter>::get (
this=0x7fffffffd6f8) at dependencies/json/json.hpp:7288
#2 0x000055555565a89f in nlohmann::detail::lexer<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> > >, nlohmann::detail::input_stream_adapter>::skip_bom (this=0x7fffffffd6f8) at dependencies/json/json.hpp:7425
#3 nlohmann::detail::lexer<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> > >, nlohmann::detail::input_stream_adapter>::scan (
this=this@entry=0x7fffffffd6f8) at dependencies/json/json.hpp:7451
#4 0x000055555565f657 in nlohmann::detail::parser<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> > >, nlohmann::detail::input_stream_adapter>::get_token (this=0x7fffffffd6d0) at dependencies/json/json.hpp:10636
#5 nlohmann::detail::parser<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> > >, nlohmann::detail::input_stream_adapter>::parser(nlohmann::detail::input_stream_adapter&&, std::function<bool (int, nlohmann::detail::parse_event_t, nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> > >&)>, bool, bool) (skip_comments=false, allow_exceptions_=true, cb=..., adapter=..., this=0x7fffffffd6d0) at dependencies/json/json.hpp:10252
#6 nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> > >::parser<nlohmann::detail::input_stream_adapter>(nlohmann::detail::input_stream_adapter, std::function<bool (int, nlohmann::detail::parse_event_t, nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> > >&)>, bool, bool) (allow_exceptions=true, ignore_comments=false, cb=..., adapter=...) at dependencies/json/json.hpp:16771
#7 nlohmann::operator>> (j=..., i=...) at dependencies/json/json.hpp:23453
#8 SettingsManager::LoadSettings (this=0x55555586fd00,
filename="\260]\252\366\377\177\000\000\240{\252\366\377\177\000\000`1\252\366\377\177\000\000\220\b\252\366\377\177\000\000\220.\252\366\377\177\000\000\240\060\252\366\377\177\000\000\200\n\252\366\377\177\000\000p\t\252\366\377\177\000\000\300\033\252\366\377\177\000\000\240\r\252\366\377\177\000\000\320z\255\366\377\177\000\000\000\v\252\366\377\177\000\000p\023\252\366\377\177\000\000\220,\252\366\377\177\000\000\000\001", '\000' <repeats 14 times>, "\230\030\272\366\377\177", '\000' <repeats 19 times>, "\377\377\377\377\377\377\377\000\377\377\377\377\377\377\377\230\030\272\366\377\177", '\000' <repeats 18 times>, "`\016\272\366\377\177\000\000"...)
at SettingsManager.cpp:76
#9 0x00005555556531ce in ResourceManager::ResourceManager (this=<optimized out>, this=<optimized out>) at ResourceManager.cpp:53
#10 0x0000555555653d3d in ResourceManager::get () at ResourceManager.cpp:29
#11 0x000055555561d552 in DeviceDetector::DeviceDetector(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::function<void (std::vector<RGBController*, std::allocator<RGBController*> >&)>) [clone .constprop.0] (name="OpenRazer", detector=..., this=<optimized out>) at ./DeviceDetector.h:14
#12 0x00005555556241c4 in _sub_I_65535_0.0 ()
#13 0x000055555576a26d in __libc_csu_init ()
#14 0x00007ffff66634f1 in __libc_start_main (main=0x5555555fb5a0 <main(int, char**)>, argc=1, argv=0x7fffffffdef8, init=0x55555576a220 <__libc_csu_init>,
fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffdee8) at ../csu/libc-start.c:279
#15 0x0000555555626d1e in _start () at /usr/include/c++/10/bits/stl_iterator.h:975