* Do not fail tile generation if debug mesh writing fails.
* Mark some functions as noexcept to better crash than have a deadlock.
* Unlock tile and remove job if there on exception while processing it.
components\lua\configuration.cpp(133): warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
components\esm3\effectlist.cpp(35): warning C4267: '=': conversion from 'size_t' to 'uint32_t', possible loss of data
components_tests\misc\testmathutil.cpp(54): warning C4305: 'argument': truncation from 'const double' to 'osg::Vec3f::value_type'
components_tests\misc\testmathutil.cpp(62): warning C4305: 'argument': truncation from 'const double' to 'osg::Vec3f::value_type'
components_tests\misc\testmathutil.cpp(131): warning C4305: 'argument': truncation from 'const double' to 'osg::Vec3f::value_type'
components_tests\misc\testmathutil.cpp(135): warning C4305: 'argument': truncation from 'const double' to 'osg::Vec3f::value_type'
components_tests\misc\testmathutil.cpp(135): warning C4305: 'argument': truncation from 'const double' to 'osg::Vec3f::value_type'
components_tests\misc\testmathutil.cpp(139): warning C4305: 'argument': truncation from 'const double' to 'osg::Vec3f::value_type'
See https://gitlab.com/OpenMW/openmw/-/issues/8370#note_2370896069.
=================================================================
==8699==ERROR: AddressSanitizer: heap-use-after-free on address 0x50800060d4b0 at pc 0x7254de50893e bp 0x7fffa97f9700 sp 0x7fffa97f96f0
READ of size 8 at 0x50800060d4b0 thread T0
#0 0x7254de50893d (/home/elsid/dev/LuaJIT/build/gcc/asan/install/lib/libluajit-5.1.so.2+0x6293d) (BuildId: 1249151684379d19b11900f406fea9704a6375cb)
#1 0x7254de50ccad in lua_rawgeti (/home/elsid/dev/LuaJIT/build/gcc/asan/install/lib/libluajit-5.1.so.2+0x66cad) (BuildId: 1249151684379d19b11900f406fea9704a6375cb)
#2 0x7254de5d4cab in luaL_unref (/home/elsid/dev/LuaJIT/build/gcc/asan/install/lib/libluajit-5.1.so.2+0x12ecab) (BuildId: 1249151684379d19b11900f406fea9704a6375cb)
#3 0x5f96378dd1e9 in sol::stateless_reference::deref(lua_State*) const /home/elsid/dev/openmw/extern/sol3/sol/reference.hpp:440
#4 0x5f96378dd1e9 in sol::basic_reference<false>::deref() const /home/elsid/dev/openmw/extern/sol3/sol/reference.hpp:545
#5 0x5f96378dd1e9 in sol::basic_reference<false>::~basic_reference() /home/elsid/dev/openmw/extern/sol3/sol/reference.hpp:635
#6 0x5f96378dd1e9 in sol::basic_object_base<sol::basic_reference<false> >::~basic_object_base() /home/elsid/dev/openmw/extern/sol3/sol/object_base.hpp:33
#7 0x5f96378dd1e9 in sol::basic_object<sol::basic_reference<false> >::~basic_object() /home/elsid/dev/openmw/extern/sol3/sol/object.hpp:35
#8 0x5f96378dd1e9 in ~<lambda> /home/elsid/dev/openmw/apps/openmw/mwlua/vfsbindings.cpp:195
#9 0x5f96378dd1e9 in ~functor_function /home/elsid/dev/openmw/extern/sol3/sol/function_types_stateful.hpp:32
#10 0x5f96378dd1e9 in destroy_at<sol::function_detail::functor_function<MWLua::initVFSPackage(const Context&)::<lambda(sol::this_state, sol::object)>::<lambda()>, false, true> > /usr/include/c++/14.2.1/bits/stl_construct.h:88
#11 0x5f96378dd1e9 in destroy<sol::function_detail::functor_function<MWLua::initVFSPackage(const Context&)::<lambda(sol::this_state, sol::object)>::<lambda()>, false, true> > /usr/include/c++/14.2.1/bits/alloc_traits.h:599
#12 0x5f96378dd1e9 in user_alloc_destroy<sol::function_detail::functor_function<MWLua::initVFSPackage(const Context&)::<lambda(sol::this_state, sol::object)>::<lambda()>, false, true> > /home/elsid/dev/openmw/extern/sol3/sol/stack_core.hpp:460
#13 0x5f963a31e305 in int sol::detail::trampoline<int (*&)(lua_State*)>(lua_State*, int (*&)(lua_State*)) /home/elsid/dev/openmw/extern/sol3/sol/trampoline.hpp:158
#14 0x5f963a31e89c in sol::detail::c_trampoline(lua_State*, int (*)(lua_State*)) /home/elsid/dev/openmw/extern/sol3/sol/trampoline.hpp:183
#15 0x7254de4dc13a (/home/elsid/dev/LuaJIT/build/gcc/asan/install/lib/libluajit-5.1.so.2+0x3613a) (BuildId: 1249151684379d19b11900f406fea9704a6375cb)
#16 0x7254de4deac4 (/home/elsid/dev/LuaJIT/build/gcc/asan/install/lib/libluajit-5.1.so.2+0x38ac4) (BuildId: 1249151684379d19b11900f406fea9704a6375cb)
#17 0x7254de4df1a2 (/home/elsid/dev/LuaJIT/build/gcc/asan/install/lib/libluajit-5.1.so.2+0x391a2) (BuildId: 1249151684379d19b11900f406fea9704a6375cb)
#18 0x7254de4e1cf2 (/home/elsid/dev/LuaJIT/build/gcc/asan/install/lib/libluajit-5.1.so.2+0x3bcf2) (BuildId: 1249151684379d19b11900f406fea9704a6375cb)
#19 0x7254de4e2a37 (/home/elsid/dev/LuaJIT/build/gcc/asan/install/lib/libluajit-5.1.so.2+0x3ca37) (BuildId: 1249151684379d19b11900f406fea9704a6375cb)
#20 0x7254de50f4a4 in lua_gc (/home/elsid/dev/LuaJIT/build/gcc/asan/install/lib/libluajit-5.1.so.2+0x694a4) (BuildId: 1249151684379d19b11900f406fea9704a6375cb)
#21 0x5f96371f615c in MWLua::LuaManager::clear() /home/elsid/dev/openmw/apps/openmw/mwlua/luamanagerimp.cpp:348
#22 0x5f96371f91ea in MWLua::LuaManager::noGame() /home/elsid/dev/openmw/apps/openmw/mwlua/luamanagerimp.cpp:397
#23 0x5f963a1c7170 in MWState::StateManager::cleanup(bool) /home/elsid/dev/openmw/apps/openmw/mwstate/statemanagerimp.cpp:71
#24 0x5f963a1cabfe in MWState::StateManager::newGame(bool) /home/elsid/dev/openmw/apps/openmw/mwstate/statemanagerimp.cpp:169
#25 0x5f963a1c7aa4 in MWState::StateManager::update(float) /home/elsid/dev/openmw/apps/openmw/mwstate/statemanagerimp.cpp:761
#26 0x5f963a230bab in OMW::Engine::frame(unsigned int, float) /home/elsid/dev/openmw/apps/openmw/engine.cpp:238
#27 0x5f963a2442f3 in OMW::Engine::go() /home/elsid/dev/openmw/apps/openmw/engine.cpp:1032
#28 0x5f963633b3a7 in runApplication(int, char**) /home/elsid/dev/openmw/apps/openmw/main.cpp:228
#29 0x5f963b375b45 in Debug::wrapApplication(int (*)(int, char**), int, char**, std::basic_string_view<char, std::char_traits<char> >) /home/elsid/dev/openmw/components/debug/debugging.cpp:457
#30 0x5f9636331695 in main /home/elsid/dev/openmw/apps/openmw/main.cpp:240
#31 0x7254db435487 (/usr/lib/libc.so.6+0x27487) (BuildId: 0b707b217b15b106c25fe51df3724b25848310c0)
#32 0x7254db43554b in __libc_start_main (/usr/lib/libc.so.6+0x2754b) (BuildId: 0b707b217b15b106c25fe51df3724b25848310c0)
#33 0x5f9636331464 in _start (/home/elsid/dev/openmw/build/gcc/asan/openmw+0x10db464) (BuildId: ac74a52ca60e8913bef6eb6b3b23d6de648cf3c9)
0x50800060d4b0 is located 16 bytes inside of 96-byte region [0x50800060d4a0,0x50800060d500)
freed by thread T0 here:
#0 0x7254e2afc102 in free /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_malloc_linux.cpp:52
#1 0x5f963a2f84e7 in LuaUtil::LuaState::trackingAllocator(void*, void*, unsigned long, unsigned long) /home/elsid/dev/openmw/components/lua/luastate.cpp:107
#2 0x7254de4f7779 (/home/elsid/dev/LuaJIT/build/gcc/asan/install/lib/libluajit-5.1.so.2+0x51779) (BuildId: 1249151684379d19b11900f406fea9704a6375cb)
#3 0x7254de4de7f3 (/home/elsid/dev/LuaJIT/build/gcc/asan/install/lib/libluajit-5.1.so.2+0x387f3) (BuildId: 1249151684379d19b11900f406fea9704a6375cb)
#4 0x7254de4e1a9a (/home/elsid/dev/LuaJIT/build/gcc/asan/install/lib/libluajit-5.1.so.2+0x3ba9a) (BuildId: 1249151684379d19b11900f406fea9704a6375cb)
#5 0x7254de4e2a37 (/home/elsid/dev/LuaJIT/build/gcc/asan/install/lib/libluajit-5.1.so.2+0x3ca37) (BuildId: 1249151684379d19b11900f406fea9704a6375cb)
#6 0x7254de50f4a4 in lua_gc (/home/elsid/dev/LuaJIT/build/gcc/asan/install/lib/libluajit-5.1.so.2+0x694a4) (BuildId: 1249151684379d19b11900f406fea9704a6375cb)
#7 0x5f96371f615c in MWLua::LuaManager::clear() /home/elsid/dev/openmw/apps/openmw/mwlua/luamanagerimp.cpp:348
#8 0x5f96371f91ea in MWLua::LuaManager::noGame() /home/elsid/dev/openmw/apps/openmw/mwlua/luamanagerimp.cpp:397
#9 0x5f963a1c7170 in MWState::StateManager::cleanup(bool) /home/elsid/dev/openmw/apps/openmw/mwstate/statemanagerimp.cpp:71
#10 0x5f963a1cabfe in MWState::StateManager::newGame(bool) /home/elsid/dev/openmw/apps/openmw/mwstate/statemanagerimp.cpp:169
#11 0x5f963a1c7aa4 in MWState::StateManager::update(float) /home/elsid/dev/openmw/apps/openmw/mwstate/statemanagerimp.cpp:761
#12 0x5f963a230bab in OMW::Engine::frame(unsigned int, float) /home/elsid/dev/openmw/apps/openmw/engine.cpp:238
#13 0x5f963a2442f3 in OMW::Engine::go() /home/elsid/dev/openmw/apps/openmw/engine.cpp:1032
#14 0x5f963633b3a7 in runApplication(int, char**) /home/elsid/dev/openmw/apps/openmw/main.cpp:228
#15 0x5f963b375b45 in Debug::wrapApplication(int (*)(int, char**), int, char**, std::basic_string_view<char, std::char_traits<char> >) /home/elsid/dev/openmw/components/debug/debugging.cpp:457
#16 0x5f9636331695 in main /home/elsid/dev/openmw/apps/openmw/main.cpp:240
#17 0x7254db435487 (/usr/lib/libc.so.6+0x27487) (BuildId: 0b707b217b15b106c25fe51df3724b25848310c0)
#18 0x7254db43554b in __libc_start_main (/usr/lib/libc.so.6+0x2754b) (BuildId: 0b707b217b15b106c25fe51df3724b25848310c0)
#19 0x5f9636331464 in _start (/home/elsid/dev/openmw/build/gcc/asan/openmw+0x10db464) (BuildId: ac74a52ca60e8913bef6eb6b3b23d6de648cf3c9)
previously allocated by thread T20 here:
#0 0x7254e2afc3c2 in realloc /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_malloc_linux.cpp:85
#1 0x5f963a2f7080 in LuaUtil::LuaState::trackingAllocator(void*, void*, unsigned long, unsigned long) /home/elsid/dev/openmw/components/lua/luastate.cpp:110
#2 0x7254de4e2fc8 (/home/elsid/dev/LuaJIT/build/gcc/asan/install/lib/libluajit-5.1.so.2+0x3cfc8) (BuildId: 1249151684379d19b11900f406fea9704a6375cb)
#3 0x7254de4f7476 (/home/elsid/dev/LuaJIT/build/gcc/asan/install/lib/libluajit-5.1.so.2+0x51476) (BuildId: 1249151684379d19b11900f406fea9704a6375cb)
#4 0x7254de50c456 in lua_newthread (/home/elsid/dev/LuaJIT/build/gcc/asan/install/lib/libluajit-5.1.so.2+0x66456) (BuildId: 1249151684379d19b11900f406fea9704a6375cb)
#5 0x7254de5d53e5 (/home/elsid/dev/LuaJIT/build/gcc/asan/install/lib/libluajit-5.1.so.2+0x12f3e5) (BuildId: 1249151684379d19b11900f406fea9704a6375cb)
#6 0x7254de4dc0c5 (/home/elsid/dev/LuaJIT/build/gcc/asan/install/lib/libluajit-5.1.so.2+0x360c5) (BuildId: 1249151684379d19b11900f406fea9704a6375cb)
Thread T20 created by T0 here:
#0 0x7254e2af44cb in pthread_create /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_interceptors.cpp:245
#1 0x7254db6e2071 in __gthread_create /usr/src/debug/gcc/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu/bits/gthr-default.h:676
#2 0x7254db6e2071 in std:🧵:_M_start_thread(std::unique_ptr<std:🧵:_State, std::default_delete<std:🧵:_State> >, void (*)()) /usr/src/debug/gcc/gcc/libstdc++-v3/src/c++11/thread.cc:172
#3 0x5f96380fa2eb in thread<MWLua::Worker::Worker(MWLua::LuaManager&)::<lambda()> > /usr/include/c++/14.2.1/bits/std_thread.h:173
#4 0x5f96380fa2eb in MWLua::Worker::Worker(MWLua::LuaManager&) /home/elsid/dev/openmw/apps/openmw/mwlua/worker.cpp:18
#5 0x5f963a23faf4 in std::__detail::_MakeUniq<MWLua::Worker>::__single_object std::make_unique<MWLua::Worker, MWLua::LuaManager&>(MWLua::LuaManager&) /usr/include/c++/14.2.1/bits/unique_ptr.h:1077
#6 0x5f963a23faf4 in OMW::Engine::prepareEngine() /home/elsid/dev/openmw/apps/openmw/engine.cpp:920
#7 0x5f963a2413ae in OMW::Engine::go() /home/elsid/dev/openmw/apps/openmw/engine.cpp:952
#8 0x5f963633b3a7 in runApplication(int, char**) /home/elsid/dev/openmw/apps/openmw/main.cpp:228
#9 0x5f963b375b45 in Debug::wrapApplication(int (*)(int, char**), int, char**, std::basic_string_view<char, std::char_traits<char> >) /home/elsid/dev/openmw/components/debug/debugging.cpp:457
#10 0x5f9636331695 in main /home/elsid/dev/openmw/apps/openmw/main.cpp:240
#11 0x7254db435487 (/usr/lib/libc.so.6+0x27487) (BuildId: 0b707b217b15b106c25fe51df3724b25848310c0)
#12 0x7254db43554b in __libc_start_main (/usr/lib/libc.so.6+0x2754b) (BuildId: 0b707b217b15b106c25fe51df3724b25848310c0)
#13 0x5f9636331464 in _start (/home/elsid/dev/openmw/build/gcc/asan/openmw+0x10db464) (BuildId: ac74a52ca60e8913bef6eb6b3b23d6de648cf3c9)
SUMMARY: AddressSanitizer: heap-use-after-free (/home/elsid/dev/LuaJIT/build/gcc/asan/install/lib/libluajit-5.1.so.2+0x6293d) (BuildId: 1249151684379d19b11900f406fea9704a6375cb)
Shadow bytes around the buggy address:
0x50800060d200: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 fa
0x50800060d280: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 fa
0x50800060d300: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 fa
0x50800060d380: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 fa
0x50800060d400: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 fa
=>0x50800060d480: fa fa fa fa fd fd[fd]fd fd fd fd fd fd fd fd fd
0x50800060d500: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x50800060d580: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x50800060d600: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x50800060d680: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x50800060d700: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==8699==ABORTING
* use the value from the existing openmw.cfg if it exists and we weren't told to use something else on the command line
* write the value to openmw.cfg if it wasn't there or we've overridden it
'#' is a valid character in setting values - it's only a comment if it's the first non-" \t\r\n" character on a line.
Making the comment ignoring match the parser we use elsewhere should avoid mangling data.
Combine the cell radius (mCellDistance) and diameter (mNumCells)
members into an offset IntRect (mGrid.) The grid is centered on the
player's current cell in exteriors (with each grid square mapping to a
cell.) In interiors, the grid is centered on the cell's computed bounds.
The number of squares remains based on view distance in exteriors, but
can now stretch to encompass arbitrarily large interiors, mostly preventing
the player from walking off the map grid (interiors exceeding their
computed bounds during gameplay still cause issues.)
Store original representation of paths in content lists. Also compare against existing content lists in a more forgiving way.
See merge request OpenMW/openmw!4424
Also compare against existing content lists in a more forgiving way.
The first improvement makes it possible to use relative paths in openmw.cfg without the launcher canonicalising them.
This was really annoying if you used a relative path on purpose.
It also stops the launcher converting all paths to Qt's convention, where forward slashes are used on Windows even though they're not native.
The engine doesn't care, so you could always put either in the config file, but the launcher wouldn't stand for that, and would make them match.
To make this work, we need to store a path's originalRepresentation in the content list, compare paths loaded from openmw.cfg based on their originalRepresentation, and convert paths from originalRepresentation to absolute value when loading them from a content list.
The second improvement means that paths that are equivalent, but expressed differently (e.g. mismatched case on Windows, mismatched separators on Windows, or mild differences like unnecessary `./`es and doubled separators) don't trigger the creation of a new effectively-identical content list.
To make this work, we had to switch the comparison to lexicaly normalise the path first.
It could only be lexical normalisation as originalRepresentation might be absolute, relative, or absolute-but-based-on-a-path-slug, and we didn't want slugs to break things or relative paths to count as equivalent to absolute ones that refer to the same file.
The comparison is case-insensitive on Windows, and case-sensitive elsewhere.
This isn't strictly right, as you can have case-sensitive things mounted on Windows or tell a Linux directory to be case-insensitive, but we can't tell when that might happen based on a lexical path as it depends on real directory properties (and might differ for different parts of the path, which is too much hassle to support).
Previously, if fed bad data, or a content list predated a BSA being moved to a non-user config file, or possibly in other situations (but not any of the obvious ones as those had other guards), the `selectedArchives` list could be longer than the number of archives available due to duplicate entries.
This ensures they're handled like entries specifying no-longer-present archives, and just skips the duplicates.
The same would happen elsewhere in similar situations, but those code paths aren't always taken.
If extension is not 2 letters length (e.g. not .kf), replacing last 3 last
charaters leads to weird results like:
"meshes/basicplayer.dae" -> "animations/basicplayer./"
According to the doc this should be "animations/basicplayer/".
Basically don't abuse OSG as badly. We need to let it know we've bound a shader program so it doesn't assume the FFP is still used, but it doesn't have a built-in way to apply the uniforms when doing so, so we need to do it manually.
Static variables should be initalized once instead of initializing them with
nullptr and then doing actual initialization behind if condition. Otherwise a
race condition may happen leading to undefined behaviour.
Boost::zlib is basically part of Boost::iostreams, and depending on how you configure Boost, it can either be a separate library or get embedded into iostreams.
With the third-party-but-linked-on-Boost's-website package we've been using for years, it's a separate library.
Before https://gitlab.com/OpenMW/openmw/-/merge_requests/4307, we needed to explicitly link with it as CMake wasn't handling transitive dependencies for us.
With vcpkg, it's embedded, and doesn't have its own CMake config, so we couldn't explicitly link with it even if we wanted to.
Now CMake *is* handling transitive dependencies for us, we don't even need to think about this library.
It's all automatic.
Boost::locale, on the other hand, used to be something we used directly (I think for doing UTF-16/UTF-8 conversions when dealing with Windows paths).
However, it isn't anymore, and we just didn't purge it from our CMake when we should have.
It can go.
Resolves https://gitlab.com/OpenMW/openmw/-/issues/8100
Also removes some old crud.
Hopefully the old crud is all:
* Handled automatically by CMake now we're using the modern approach.
* A hack-fix for a problem caused by not using the modern approach.
* Massively outdated so no longer necessary.
If it turns out this makes CI fail, I'll tweak things as necessary.
Changes that might not be wanted include:
* Getting rid of our BOOST_STATIC CMake option. In cases where the CMake config doesn't make the one correct choice from the build environment (i.e. because there's a choice) the CMake config exposes the option already.
However, we were forcing this on for Windows, so that might matter.
It seems to default to static on my machine even though I thought I read something suggesting otherwise, so we'll see how things go with that.
If we eventually put CMake in charge of installing dependency DLLs this will be a moot point as we won't need to care.
* Bumping the minimum version of Boost to 1.70.0, as that's the first with working CMake config.
It's from 2019, so plausibly there are distros too scared to use a library from five years ago as it can't legally drink in the US (although it could in limited quantities with parental supervision in the UK, as long as it's just something inconsequential like a single sip of beer).