VOGONS


Broken executables with MinGW-w64 (GZDoom)

Topic actions

Reply 40 of 65, by dondiego

User metadata
Rank Member
Rank
Member

Well, may be x64 edition's 64 bit performance wasn't great either, but probably it's a MinGW thing.
There was another problem, the -iwad parameter didn't work properly (bad iwad search path) with MinGW so iwads could not be launched with ZDL if not in the GZDoom folder but it's fixed now.

LZDoom, ZDoom32, ZDoom LE
RUDE (Doom)
Romero's Heresy II (Heretic)

Reply 41 of 65, by hail-to-the-ryzen

User metadata
Rank Member
Rank
Member
hail-to-the-ryzen wrote:

Two issues with the tdm-gcc-32 build:
1. r_multithreaded=1 not working with the SSE2 truecolor software renderer
2. crashes on exit regardless of renderer

For #1, testing with these flags for debug build: -g -mincoming-stack-boundary=2 -msse2 -mfpmath=sse

Reply 42 of 65, by hail-to-the-ryzen

User metadata
Rank Member
Rank
Member

gcc thread_local destructor cause use after free; https://github.com/Alexpux/MINGW-packages/issues/2519:
"Don't use thread_local on GCC for MinGW targets."

Testing alternatives, such as:
#define thread_local __declspec(thread)

Reply 43 of 65, by dondiego

User metadata
Rank Member
Rank
Member

Actually that was discussed in the ZDoom thread linked earlier. I removed thread_local from VMFrameStack GlobalVMStack as Graf suggested and still crashed. That __declspec(thread) thing is for VS and it won't compile with __thread either since that object needs to be allocated dynamically.
So i didn't mention it was a thread local variable in the bug report. Something similar happened with the FMaterial destructor in the old GL renderer (gzdoom32 branch).

LZDoom, ZDoom32, ZDoom LE
RUDE (Doom)
Romero's Heresy II (Heretic)

Reply 44 of 65, by hail-to-the-ryzen

User metadata
Rank Member
Rank
Member

Both those changes seem to fix issues 1 and 2. Limited testing.

Reply 46 of 65, by hail-to-the-ryzen

User metadata
Rank Member
Rank
Member

It works now with tdm-gcc-32. Working on a W95 static build by an alternative method.

Reply 48 of 65, by hail-to-the-ryzen

User metadata
Rank Member
Rank
Member

I'm trying to pair mingw32 with a lightweight std::thread library. I'll try to reproduce that issue, too.

Reply 49 of 65, by dondiego

User metadata
Rank Member
Rank
Member

But it is fixed now or not?
I forgot to mention the GL renderer won't run on win95, there are a lot of win98 function calls, only ancient versions did.
Today i found a tower near a trash container, k6-2 500 on a gigabyte ga-5ax board with a sis 6326, sb pci and a dead hdd. Perhaps i could test there. 😀
Edit: perhaps the crash is cpu speed dependant.

LZDoom, ZDoom32, ZDoom LE
RUDE (Doom)
Romero's Heresy II (Heretic)

Reply 50 of 65, by hail-to-the-ryzen

User metadata
Rank Member
Rank
Member

I only tested issues #1 and #2 from above. Here is another method:
https://www.reddit.com/r/cpp/comments/6fitru/ … boost_1640_for/

They describe using boost:🧵

I see that you are not linking against winpthread like the upstream mingw. How exactly does this work?

Boost.Thread calls the Win32 API directly. I don't know how GCC's thread_local implementation works; possibly they're directly calling the Win32 API too, even as libstdc++ wants to call pthreads.

AFAIK the mingw64 upstream uses gcc's emutls which result in some calls to pthread_key_create and friends, and that is quite buggy.

And that's why I run away screaming from pthreads wrappers.

Which flags do I need to pass to gcc to get whatever configuration you have?

See mingw-w64+gcc.sh on GitHub.
https://github.com/StephanTLavavej/mingw-distro/blob/master/mingw-w64%2Bgcc.sh

Reply 51 of 65, by dondiego

User metadata
Rank Member
Rank
Member

Removing thread_local won't help here. Also that boost solution is not acceptable in GZDoom (neither the hack) but could be in a fork. Anyway that's a 64 bit unofficial build (or repackage) and that's not the recommended way of creating 32 bit executables.
Also the crash on exit in the FMaterial destructor in the GL renderer almost certainly is still there.
Edit: no, that one is gone.
I don't think using a non standard C++ library is a good idea anyway, it would compile only with that distro.

LZDoom, ZDoom32, ZDoom LE
RUDE (Doom)
Romero's Heresy II (Heretic)

Reply 53 of 65, by hail-to-the-ryzen

User metadata
Rank Member
Rank
Member

Nice work as always! I had difficulty running the gdb debugger with some debug builds, but I guess that you had no such issue.

Maybe the mingw-w64 and gcc teams will fix any outstanding C++11 threads issues. These seem to have been documented for at least a few years.

Reply 54 of 65, by dondiego

User metadata
Rank Member
Rank
Member

Thanks, but i was kidding when i said it was an elegant solution. 🤣 It's just a quick hack to prevent the crash.
Also i've just fixed a couple of bad merges. 😵 I haven't pushed the hack yet becouse i'm waiting for the MinGW-w64 devs but i don't actually think they'll look into it, also i think that thread_local thing is hopeless at least for now.
No problem debugging here but i use Code::Blocks mostly. I usually compile from the command line since the IDE most times won't catch the -j2 parameter.

LZDoom, ZDoom32, ZDoom LE
RUDE (Doom)
Romero's Heresy II (Heretic)

Reply 55 of 65, by hail-to-the-ryzen

User metadata
Rank Member
Rank
Member

I think it is an impressive workaround and provides a guide for future instances of that issue. 😀

I recall there was a similar bug reported at zdoom in older versions of *bsd, perhaps openbsd and a recent gcc? If that is true, why does gcc and c++11 threads only work for linux?

The debugger worked for me and then it didn't. 🙁 I was somewhat lax and used MSYS from a mingw32 installation. Edited /etc/fstab so that it pointed to tdm-gcc-32 instead; along with dx9 header files.

Reply 56 of 65, by dondiego

User metadata
Rank Member
Rank
Member

You don't need MSYS at all, i use Code::Blocks but compile from the windows command line increasing the buffer for cmd for convenience.
It's better to debug from the IDE. Just remember that in tdm-gcc the debugger is called gdb32 and not just gdb.
Of course i added the path to the MinGW binaries to the system path (editing Path in advanced system properties).
Also i've got MSYS2 installed for MinGW-w64 (but it's not required either).
The DirectX libraries are included in the MinGW package.
I wrote a couple of mini-guides @ https://forum.zdoom.org/viewtopic.php?f=4&t=60338

LZDoom, ZDoom32, ZDoom LE
RUDE (Doom)
Romero's Heresy II (Heretic)

Reply 58 of 65, by mockingbird

User metadata
Rank Oldbie
Rank
Oldbie

I went from a GeForce GTX650 down to a GeForce 9800GT and it went from this:

mockingbird wrote:

32-bit build
timed 4848 gametics in 971 realtics (174.7 fps)

To this:
timed 1756 gametics in 860 realtics (71.5 fps)

mslrlv.png
(Decommissioned:)
7ivtic.png

Reply 59 of 65, by hail-to-the-ryzen

User metadata
Rank Member
Rank
Member

I think the code below is the cause, or at least one of the causes, of the thread_local issue in mingw-w64. This code is in the libc++ library which then references the libc function __cxa_thread_atexit. Some untested changes are below to instead use a different code path for testing. LLVM handled it with a different solution: https://reviews.llvm.org/D21803.

--- atexit_thread-Orig.cc	2018-05-19 20:59:35 -0400
+++ atexit_thread.cc 2018-05-19 21:23:36 -0400
@@ -25,16 +25,16 @@
#include <cstdlib>
#include <new>
#include "bits/gthr.h"
-#ifdef _GLIBCXX_THREAD_ATEXIT_WIN32
+#if 1 // #ifdef _GLIBCXX_THREAD_ATEXIT_WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif

-#if _GLIBCXX_HAVE___CXA_THREAD_ATEXIT
+#if 0 // _GLIBCXX_HAVE___CXA_THREAD_ATEXIT

// Libc provides __cxa_thread_atexit definition.

-#elif _GLIBCXX_HAVE___CXA_THREAD_ATEXIT_IMPL
+#elif 0 // _GLIBCXX_HAVE___CXA_THREAD_ATEXIT_IMPL

extern "C" int __cxa_thread_atexit_impl (void (*func) (void *),
void *arg, void *d);
@@ -55,13 +55,13 @@ namespace {
void (*destructor)(void *);
void *object;
elt *next;
-#ifdef _GLIBCXX_THREAD_ATEXIT_WIN32
+#if 1 // #ifdef _GLIBCXX_THREAD_ATEXIT_WIN32
HMODULE dll;
#endif
};

- // Keep a per-thread list of cleanups in gthread_key storage.
- __gthread_key_t key;
+ // Keep a per-thread list of cleanups in pthread_key storage.
+ pthread_key_t key;
// But also support non-threaded mode.
elt *single_thread;

@@ -73,7 +73,7 @@ namespace {
{
elt *old_e = e;
e->destructor (e->object);
-#ifdef _GLIBCXX_THREAD_ATEXIT_WIN32
+#if 1 // #ifdef _GLIBCXX_THREAD_ATEXIT_WIN32
/* Decrement DLL count */
if (e->dll)
FreeLibrary (e->dll);
@@ -87,10 +87,10 @@ namespace {
void run ()
{
void *e;
- if (__gthread_active_p ())
+ if (1/*__gthread_active_p ()*/)
{
- e = __gthread_getspecific (key);
- __gthread_setspecific (key, NULL);
+ e = pthread_getspecific (key);
+ pthread_setspecific (key, NULL);
}
Show last 61 lines
     else
{
@@ -104,8 +104,8 @@ namespace {
// key init/delete rather than atexit so that delete is run on dlclose.
void key_init() {
struct key_s {
- key_s() { __gthread_key_create (&key, run); }
- ~key_s() { __gthread_key_delete (key); }
+ key_s() { pthread_key_create (&key, run); }
+ ~key_s() { pthread_key_delete (key); }
};
static key_s ks;
// Also make sure the destructors are run by std::exit.
@@ -120,11 +120,11 @@ __cxxabiv1::__cxa_thread_atexit (void (*
_GLIBCXX_NOTHROW
{
// Do this initialization once.
- if (__gthread_active_p ())
+ if (1/*__gthread_active_p ()*/)
{
- // When threads are active use __gthread_once.
- static __gthread_once_t once = __GTHREAD_ONCE_INIT;
- __gthread_once (&once, key_init);
+ // When threads are active use pthread_once.
+ static pthread_once_t once = PTHREAD_ONCE_INIT;
+ pthread_once (&once, key_init);
}
else
{
@@ -138,8 +138,8 @@ __cxxabiv1::__cxa_thread_atexit (void (*
}

elt *first;
- if (__gthread_active_p ())
- first = static_cast<elt*>(__gthread_getspecific (key));
+ if (1/*__gthread_active_p ()*/)
+ first = static_cast<elt*>(pthread_getspecific (key));
else
first = single_thread;

@@ -149,7 +149,7 @@ __cxxabiv1::__cxa_thread_atexit (void (*
new_elt->destructor = dtor;
new_elt->object = obj;
new_elt->next = first;
-#ifdef _GLIBCXX_THREAD_ATEXIT_WIN32
+#if 1 // #ifdef _GLIBCXX_THREAD_ATEXIT_WIN32
/* Store the DLL address for a later call to FreeLibrary in new_elt and
increment DLL load count. This blocks the unloading of the DLL
before the thread-local dtors have been called. This does NOT help
@@ -158,8 +158,8 @@ __cxxabiv1::__cxa_thread_atexit (void (*
(LPCWSTR) dtor, &new_elt->dll);
#endif

- if (__gthread_active_p ())
- __gthread_setspecific (key, new_elt);
+ if (1/*__gthread_active_p ()*/)
+ pthread_setspecific (key, new_elt);
else
single_thread = new_elt;