Broken executables with MinGW-w64 (GZDoom)

Announcements, advice, random banter, unrelated discussion, et cetera.

Re: Broken executables with MinGW-w64 (GZDoom)

Postby dondiego » 2018-5-12 @ 20:16

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.
User avatar
dondiego
Member
 
Posts: 283
Joined: 2013-12-24 @ 12:31
Location: Spain

Re: Broken executables with MinGW-w64 (GZDoom)

Postby hail-to-the-ryzen » 2018-5-12 @ 23:25

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
hail-to-the-ryzen
Member
 
Posts: 186
Joined: 2017-3-09 @ 01:34

Re: Broken executables with MinGW-w64 (GZDoom)

Postby hail-to-the-ryzen » 2018-5-13 @ 05:31

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)
hail-to-the-ryzen
Member
 
Posts: 186
Joined: 2017-3-09 @ 01:34

Re: Broken executables with MinGW-w64 (GZDoom)

Postby dondiego » 2018-5-13 @ 11:58

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).
User avatar
dondiego
Member
 
Posts: 283
Joined: 2013-12-24 @ 12:31
Location: Spain

Re: Broken executables with MinGW-w64 (GZDoom)

Postby hail-to-the-ryzen » 2018-5-13 @ 17:39

Both those changes seem to fix issues 1 and 2. Limited testing.
hail-to-the-ryzen
Member
 
Posts: 186
Joined: 2017-3-09 @ 01:34

Re: Broken executables with MinGW-w64 (GZDoom)

Postby dondiego » 2018-5-13 @ 17:51

Which changes? I removed the thread_local keyword before VMFrameStack GlobalVMStack and still crashed here.
User avatar
dondiego
Member
 
Posts: 283
Joined: 2013-12-24 @ 12:31
Location: Spain

Re: Broken executables with MinGW-w64 (GZDoom)

Postby hail-to-the-ryzen » 2018-5-13 @ 17:56

It works now with tdm-gcc-32. Working on a W95 static build by an alternative method.
hail-to-the-ryzen
Member
 
Posts: 186
Joined: 2017-3-09 @ 01:34

Re: Broken executables with MinGW-w64 (GZDoom)

Postby dondiego » 2018-5-13 @ 18:12

It didn't work for me with tdm-gcc 5.1 on win 8.1. Which OS are you using? About win95 98 already had those timing issues (half the framerate).
User avatar
dondiego
Member
 
Posts: 283
Joined: 2013-12-24 @ 12:31
Location: Spain

Re: Broken executables with MinGW-w64 (GZDoom)

Postby hail-to-the-ryzen » 2018-5-13 @ 19:29

I'm trying to pair mingw32 with a lightweight std::thread library. I'll try to reproduce that issue, too.
hail-to-the-ryzen
Member
 
Posts: 186
Joined: 2017-3-09 @ 01:34

Re: Broken executables with MinGW-w64 (GZDoom)

Postby dondiego » 2018-5-13 @ 19:32

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. :happy:
Edit: perhaps the crash is cpu speed dependant.
User avatar
dondiego
Member
 
Posts: 283
Joined: 2013-12-24 @ 12:31
Location: Spain

Re: Broken executables with MinGW-w64 (GZDoom)

Postby hail-to-the-ryzen » 2018-5-13 @ 21:29

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

They describe using boost::thread:
Code: Select all
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
hail-to-the-ryzen
Member
 
Posts: 186
Joined: 2017-3-09 @ 01:34

Re: Broken executables with MinGW-w64 (GZDoom)

Postby dondiego » 2018-5-14 @ 08:23

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.
User avatar
dondiego
Member
 
Posts: 283
Joined: 2013-12-24 @ 12:31
Location: Spain

Re: Broken executables with MinGW-w64 (GZDoom)

Postby dondiego » 2018-5-14 @ 16:41

I've removed the thread_local keyword and tried the hack, it works only when also making that variable non thread local.
https://forum.zdoom.org/viewtopic.php?f ... 5#p1054208
User avatar
dondiego
Member
 
Posts: 283
Joined: 2013-12-24 @ 12:31
Location: Spain

Re: Broken executables with MinGW-w64 (GZDoom)

Postby hail-to-the-ryzen » 2018-5-14 @ 17:02

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.
hail-to-the-ryzen
Member
 
Posts: 186
Joined: 2017-3-09 @ 01:34

Re: Broken executables with MinGW-w64 (GZDoom)

Postby dondiego » 2018-5-15 @ 11:33

Thanks, but i was kidding when i said it was an elegant solution. :lol: It's just a quick hack to prevent the crash.
Also i've just fixed a couple of bad merges. :dead: 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.
User avatar
dondiego
Member
 
Posts: 283
Joined: 2013-12-24 @ 12:31
Location: Spain

Re: Broken executables with MinGW-w64 (GZDoom)

Postby hail-to-the-ryzen » 2018-5-15 @ 17:03

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.
hail-to-the-ryzen
Member
 
Posts: 186
Joined: 2017-3-09 @ 01:34

Re: Broken executables with MinGW-w64 (GZDoom)

Postby dondiego » 2018-5-15 @ 17:53

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
User avatar
dondiego
Member
 
Posts: 283
Joined: 2013-12-24 @ 12:31
Location: Spain

Re: Broken executables with MinGW-w64 (GZDoom)

Postby dondiego » 2018-5-17 @ 11:25

I've pushed the hack for the crash on exit and updated the MinGW bug report accordingly, it can take them one month to reply.
User avatar
dondiego
Member
 
Posts: 283
Joined: 2013-12-24 @ 12:31
Location: Spain

Re: Broken executables with MinGW-w64 (GZDoom)

Postby mockingbird » 2018-5-18 @ 01:39

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)
Image
mockingbird
Member
 
Posts: 424
Joined: 2013-6-17 @ 02:57

Re: Broken executables with MinGW-w64 (GZDoom)

Postby hail-to-the-ryzen » 2018-5-20 @ 01:37

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.
Code: Select all
--- 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);
       }
     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;
 
hail-to-the-ryzen
Member
 
Posts: 186
Joined: 2017-3-09 @ 01:34

PreviousNext

Return to Milliways

Who is online

Users browsing this forum: No registered users and 4 guests