Cesium3DTileset::BeginPlay crash inside UE5.2 docker container

Hi,

We are experiencing a startup crash when running a project inside of the official 5.2.1 UE Linux docker container.
Since the UE docker image does not include the CesiumForUnreal plugin, we had it integrated into the project as a project plugin.
The crash callstack suggests that CesiumAsync SqliteCache fails to crate connection. Our current working theory is that Cesium uses UE’s sqlite3 library instead of its own, but we haven’t been able to confirm this yet.

Here’s the full callstack:

2023-09-15T11:42:03.154744000Z,Unhandled Exception: SIGABRT: abort() called," Exception: SIGABRT: abort() called"
2023-09-15T11:42:03.154748000Z,,
2023-09-15T11:42:03.154756000Z,,
2023-09-15T11:42:03.154760000Z,0x00007fa9f457000b libc.so.6!gsignal(+0xcb)," libc.so.6!gsignal(+0xcb)"
2023-09-15T11:42:03.154763000Z,0x00007fa9f454f859 libc.so.6!abort(+0x12a)," libc.so.6!abort(+0x12a)"
2023-09-15T11:42:03.154797000Z,0x00007fa9ffdae9b6 libNvmlWrapper.so!UnknownFunction(0x4f9b5)," libNvmlWrapper.so!UnknownFunction(0x4f9b5)"
2023-09-15T11:42:03.154802000Z,0x00007fa9ffd92d9b libNvmlWrapper.so!UnknownFunction(0x33d9a)," libNvmlWrapper.so!UnknownFunction(0x33d9a)"
2023-09-15T11:42:03.154807000Z,0x00007fa9ffd92c73 libNvmlWrapper.so!UnknownFunction(0x33c72)," libNvmlWrapper.so!UnknownFunction(0x33c72)"
2023-09-15T11:42:03.154811000Z,0x00007fa9ffdb09d6 libNvmlWrapper.so!UnknownFunction(0x519d5)," libNvmlWrapper.so!UnknownFunction(0x519d5)"
2023-09-15T11:42:03.154816000Z,0x00007fa9ffdb096f libNvmlWrapper.so!__cxa_throw(+0x6e)," libNvmlWrapper.so!__cxa_throw(+0x6e)"
2023-09-15T11:42:03.154821000Z,0x000000000db0ca75 [REDACTED]!CesiumAsync::SqliteCache::createConnection() const()," [REDACTED]!CesiumAsync::SqliteCache::createConnection() const()"
2023-09-15T11:42:03.154828000Z,"0x000000000db0c736 [REDACTED]!CesiumAsync::SqliteCache::SqliteCache(std::__1::shared_ptr<spdlog::logger> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned long)()"," [REDACTED]!CesiumAsync::SqliteCache::SqliteCache(std::__1::shared_ptr<spdlog::logger> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned long)()"
2023-09-15T11:42:03.154837000Z,"0x0000000004d87c1b [REDACTED]!std::__1::make_shared<CesiumAsync::SqliteCache, std::__1::shared_ptr<spdlog::logger>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, int &, void> [/home/ue4/UnrealEngine/Engine/Source/ThirdParty/Unix/LibCxx/include/c++/v1/__memory/shared_ptr.h:962]"," [REDACTED]!std::__1::make_shared<CesiumAsync::SqliteCache, std::__1::shared_ptr<spdlog::logger>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, int &, void> [/home/ue4/UnrealEngine/Engine/Source/ThirdParty/Unix/LibCxx/include/c++/v1/__memory/shared_ptr.h:962]"
2023-09-15T11:42:03.154842000Z,0x0000000004d87406 [REDACTED]!getAssetAccessor() [/tmp/project/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumRuntime.cpp:113]," [REDACTED]!getAssetAccessor() [/tmp/project/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumRuntime.cpp:113]"
2023-09-15T11:42:03.154847000Z,0x0000000004d568f0 [REDACTED]!ACesium3DTileset::LoadTileset() [/tmp/project/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Cesium3DTileset.cpp:920]," [REDACTED]!ACesium3DTileset::LoadTileset() [/tmp/project/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Cesium3DTileset.cpp:920]"
2023-09-15T11:42:03.154852000Z,0x0000000004d563b1 [REDACTED]!ACesium3DTileset::BeginPlay() [/tmp/project/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Cesium3DTileset.cpp:570]," [REDACTED]!ACesium3DTileset::BeginPlay() [/tmp/project/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Cesium3DTileset.cpp:570]"

Cesium for Unreal has its own private copy of SQLite with all of the symbols renamed, to avoid the exact problem you’ve described. Are you using a copy of the plugin from our Releases page on GitHub? Or installed from the Unreal Marketplace? Or built yourself?

SqliteCache::createConnection will throw an exception if it can’t open the database. But in a shipping game, an exception will cause the process to terminate. So to debug this, I’d suggest building a debug version of your application and see if the exception message offers any hints about what is going wrong.

This actually happens in a Development build.
We mount all build artifacts as read only in the docker container file system. Is the sqlite cache file generated at runtime, or during the packaging process? If it’s a build artifacts, then that would explain why Cesium wouldn’t be able to write to it at runtime.

pon., 18 wrz 2023, 11:04 użytkownik Kevin Ring via Cesium Community <notifications@cesium.discoursemail.com> napisał:

Try a Debug build, rather than Development. It should be possible to get that exception text somehow. Explicitly enabling exceptions in your project’s .build.cs might help, too.

The sqlite database isn’t created by the build process exactly, but it is created the first time Cesium for Unreal does any sort of HTTP request. So it’s possible it ends up being created during the packaging process.

There should also be a message in the log indicating the full path to the sqlite DB that Cesium for Unreal is attempting to use.

Unfortunately it’s not possible to use the Debug target when building inside the official UE containers. We are pursuing a new lead we have - that mounting our project as read only inside the runtime pod causes this issue. I’ll report back once we have investigated this angle.

We have tracked this down to an issue in our container provisioning logic. We mount the engine as a shared, read only volume mount. Cesium was failing to write the sqlite DB cache to the Engine/ directory due to that. We fixed this by specifying a user dir using the -UserDir= launch argument.
Thanks for the help!