Nim icon indicating copy to clipboard operation
Nim copied to clipboard

Windows gcc shipped with choosenim 1.6.4 with TLS emulation turned off : The application was unable to start correctly (0xc000007b). Click OK to close the application

Open creikey opened this issue 2 years ago • 19 comments

Hello world fails with this error:

The application was unable to start correctly (0xc000007b). Click OK to close the application

building with nim r --threads:on hello.nim without --threads:on it works with the file:

echo "hello"

On windows 11 nim 1.6.4 on a fresh install

This worked on nim 1.6.0

image

I completely deleted .choosenim, .nimble, nimcache, cleared the path variables, then reinstalled nim once by downloading from the website, which didn't work, then again with choosenim, which also didn't work.

Nim Compiler Version 1.6.4 [Windows: amd64]
Compiled at 2022-02-09
Copyright (c) 2006-2021 by Andreas Rumpf

active boot switches: -d:release

creikey avatar Apr 12 '22 04:04 creikey

Cannot reproduce on win11

Nim Compiler Version 1.6.4 [Windows: amd64]
Compiled at 2022-02-09
Copyright (c) 2006-2021 by Andreas Rumpf

active boot switches: -d:release

ringabout avatar Apr 12 '22 04:04 ringabout

Cannot reproduce on win11

Nim Compiler Version 1.6.4 [Windows: amd64]
Compiled at 2022-02-09
Copyright (c) 2006-2021 by Andreas Rumpf

active boot switches: -d:release

did you try compiling hello with --threads:on?

creikey avatar Apr 12 '22 04:04 creikey

Yeah, I testsed with --threads:on

echo "hello"

doAssert compileOption("threads")

ringabout avatar Apr 12 '22 04:04 ringabout

Because it's an issue with threads, I suspect it's some kind of path confusion with what threads dll it's linking with, but I have no idea how to check something like this...

creikey avatar Apr 12 '22 04:04 creikey

You could use --listCmd to see the call to your C compiler and see if anything doesn't make sense.

beef331 avatar Apr 12 '22 07:04 beef331

You could use --listCmd to see the call to your C compiler and see if anything doesn't make sense.

Thanks for the troubleshooting tip

Everything is ran like

nim --threads:on --listCmd r -f hello.nim
CC: stdlib_digitsutils.nim: gcc.exe -c  -w -fmax-errors=3 -mno-ms-bitfields   -IC:\Users\Cameron\.choosenim\toolchains\nim-1.6.4\lib -IC:\Users\Cameron\Documents -o C:\Users\Cameron\nimcache\hello_d\stdlib_digitsutils.nim.c.o C:\Users\Cameron\nimcache\hello_d\stdlib_digitsutils.nim.c
CC: stdlib_dollars.nim: gcc.exe -c  -w -fmax-errors=3 -mno-ms-bitfields   -IC:\Users\Cameron\.choosenim\toolchains\nim-1.6.4\lib -IC:\Users\Cameron\Documents -o C:\Users\Cameron\nimcache\hello_d\stdlib_dollars.nim.c.o C:\Users\Cameron\nimcache\hello_d\stdlib_dollars.nim.c
CC: stdlib_sharedlist.nim: gcc.exe -c  -w -fmax-errors=3 -mno-ms-bitfields   -IC:\Users\Cameron\.choosenim\toolchains\nim-1.6.4\lib -IC:\Users\Cameron\Documents -o C:\Users\Cameron\nimcache\hello_d\stdlib_sharedlist.nim.c.o C:\Users\Cameron\nimcache\hello_d\stdlib_sharedlist.nim.c
CC: stdlib_io.nim: gcc.exe -c  -w -fmax-errors=3 -mno-ms-bitfields   -IC:\Users\Cameron\.choosenim\toolchains\nim-1.6.4\lib -IC:\Users\Cameron\Documents -o C:\Users\Cameron\nimcache\hello_d\stdlib_io.nim.c.o C:\Users\Cameron\nimcache\hello_d\stdlib_io.nim.c
CC: stdlib_system.nim: gcc.exe -c  -w -fmax-errors=3 -mno-ms-bitfields   -IC:\Users\Cameron\.choosenim\toolchains\nim-1.6.4\lib -IC:\Users\Cameron\Documents -o C:\Users\Cameron\nimcache\hello_d\stdlib_system.nim.c.o C:\Users\Cameron\nimcache\hello_d\stdlib_system.nim.c
CC: hello.nim: gcc.exe -c  -w -fmax-errors=3 -mno-ms-bitfields   -IC:\Users\Cameron\.choosenim\toolchains\nim-1.6.4\lib -IC:\Users\Cameron\Documents -o C:\Users\Cameron\nimcache\hello_d\@mhello.nim.c.o C:\Users\Cameron\nimcache\hello_d\@mhello.nim.c

These are compiling the .o files, nothing weird here

Here is the linking

Hint: gcc.exe   -o C:\Users\Cameron\nimcache\hello_d\hello_7D9E602FA2A89065BE0A59241375AEACB65D60A1.exe  C:\Users\Cameron\nimcache\hello_d\stdlib_digitsutils.nim.c.o C:\Users\Cameron\nimcache\hello_d\stdlib_dollars.nim.c.o C:\Users\Cameron\nimcache\hello_d\stdlib_sharedlist.nim.c.o C:\Users\Cameron\nimcache\hello_d\stdlib_io.nim.c.o C:\Users\Cameron\nimcache\hello_d\stdlib_system.nim.c.o C:\Users\Cameron\nimcache\hello_d\@mhello.nim.c.o     [Link]

It looks like it's just linking the .o files it compiled earlier with no extra flags? What does --threads:on actually change? where gcc.exe returns the proper path by the way

where gcc.exe
C:\Users\Cameron\.nimble\bin\gcc.exe

creikey avatar Apr 12 '22 08:04 creikey

Diffing the generated C with threads on (left) vs threads off (right) image

This is the only difference in hello.c (from hello.nim)

Similar results in the standard library compiled C image

NIM_THREADVAR is just this image

Apart from CLANG_NO_SANITIZE_ADDRESS which I could not find the meaning of, I've tried to duplicate the error in a plain C file with as minimal code as possible to no such luck

#include <stdio.h>

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112 && !defined __STDC_NO_THREADS__
#  define NIM_THREADVAR _Thread_local
#elif defined _WIN32 && ( \
       defined _MSC_VER || \
       defined __ICL || \
       defined __DMC__ || \
       defined __BORLANDC__ )
#  define NIM_THREADVAR __declspec(thread)
#elif defined(__TINYC__) || defined(__GENODE__)
#  define NIM_THREADVAR
/* note that ICC (linux) and Clang are covered by __GNUC__ */
#elif defined __GNUC__ || \
       defined __SUNPRO_C || \
       defined __xlC__
#  define NIM_THREADVAR __thread
#else
#  error "Cannot define NIM_THREADVAR"
#endif

typedef char* NCSTRING;
typedef signed short int NI16;
typedef __int64 NI64;
typedef NI64 NI;

typedef struct TFrame_ TFrame;
struct TFrame_ {
  TFrame* prev;
  NCSTRING procname;
  NI line;
  NCSTRING filename;
  NI16 len;
  NI16 calldepth;
  NI frameMsgLen;
};

#  define N_LIB_PRIVATE


extern NIM_THREADVAR TFrame * framePtr__system_3025;
N_LIB_PRIVATE NIM_THREADVAR TFrame* framePtr__system_3025;


int main(int argc, char ** argv) {
        printf("Hello\n");
}

This compiles and runs fine

creikey avatar Apr 12 '22 08:04 creikey

MSVC compiler works with no issues

nim --threads:on r --cc:vcc hello.nim
Hint: used config file 'C:\Users\Cameron\.choosenim\toolchains\nim-1.6.4\config\nim.cfg' [Conf]
Hint: used config file 'C:\Users\Cameron\.choosenim\toolchains\nim-1.6.4\config\config.nims' [Conf]
.................................................................
CC: stdlib_digitsutils.nim
CC: stdlib_dollars.nim
CC: stdlib_sharedlist.nim
CC: stdlib_io.nim
CC: stdlib_system.nim
CC: hello.nim
stdlib_sharedlist.nim.c
stdlib_digitsutils.nim.c
stdlib_io.nim.c
@mhello.nim.c
stdlib_system.nim.c
stdlib_dollars.nim.c
Hint:  [Link]
Hint: gc: refc; threads: on; opt: none (DEBUG BUILD, `-d:release` generates faster code)
28676 lines; 5.999s; 31.648MiB peakmem; proj: C:\Users\Cameron\Documents\hello.nim; out: C:\Users\Cameron\nimcache\hello_d\hello_4121733DA6CB1D320C1A2E318F8C2FC0B9E0FB70.exe [SuccessX]
Hint: C:\Users\Cameron\nimcache\hello_d\hello_4121733DA6CB1D320C1A2E318F8C2FC0B9E0FB70.exe  [Exec]
Hello

creikey avatar Apr 13 '22 02:04 creikey

It works on 1.6.0

creikey avatar Apr 14 '22 05:04 creikey

Does the error only happen if using gcc as a backend? Could you tell which gcc you use with: gcc -v.

If it's the mingw64 gcc provided by the nim website, try these others and see if the error persists: https://github.com/jmeubank/tdm-gcc/releases/download/v10.3.0-tdm64-2/tdm64-gcc-10.3.0-2.exe https://github.com/brechtsanders/winlibs_mingw/releases/download/11.2.0-10.0.0-msvcrt-r1/winlibs-x86_64-posix-seh-gcc-11.2.0-mingw-w64msvcrt-10.0.0-r1.7z

Also you can check with llvm/clang.

rockcavera avatar Apr 14 '22 18:04 rockcavera

@creikey can you compile on 1.6.4 with --tlsEmulation:on and see if it works?

In 1.6.0, on Windows, it was standard to compile with --tlsEmulation:on. Not in 1.6.4.

rockcavera avatar Apr 14 '22 19:04 rockcavera

@rockcavera it only happens when using gcc as a backend yes. I use the gcc shipped with choosenim, here is the gcc -v

C:\Users\Cameron\Documents>C:\Users\Cameron\.nimble\bin\gcc.exe -v
Using built-in specs.
COLLECT_GCC=C:\Users\Cameron\.choosenim\toolchains\mingw64\bin\gcc.exe
COLLECT_LTO_WRAPPER=c:/users/cameron/.choosenim/toolchains/mingw64/bin/../libexec/gcc/x86_64-w64-mingw32/11.1.0/lto-wrapper.exe
OFFLOAD_TARGET_NAMES=nvptx-none
Target: x86_64-w64-mingw32
Configured with: ../configure --prefix=/R/winlibs64_stage/inst_gcc-11.1.0/share/gcc --build=x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --enable-offload-targets=nvptx-none --with-pkgversion='MinGW-W64 x86_64-posix-seh, built by Brecht Sanders' --with-tune=generic --enable-checking=release --enable-threads=posix --disable-sjlj-exceptions --disable-libunwind-exceptions --disable-serial-configure --disable-bootstrap --enable-host-shared --enable-plugin --disable-default-ssp --disable-rpath --enable-libstdcxx-pch --enable-libstdcxx-time=yes --disable-libstdcxx-debug --disable-version-specific-runtime-libs --with-stabs --disable-symvers --enable-languages=c,c++,fortran,lto,objc,obj-c++,d,jit --disable-gold --disable-nls --disable-stage1-checking --disable-win32-registry --disable-multilib --enable-ld --enable-libquadmath --enable-libada --enable-libssp --enable-libstdcxx --enable-lto --enable-fully-dynamic-string --enable-libgomp --enable-graphite --enable-mingw-wildcard --with-mpc=/d/Prog/winlibs64_stage/custombuilt --with-mpfr=/d/Prog/winlibs64_stage/custombuilt --with-gmp=/d/Prog/winlibs64_stage/custombuilt --with-isl=/d/Prog/winlibs64_stage/custombuilt --enable-install-libiberty --enable-__cxa_atexit --without-included-gettext --with-diagnostics-color=auto --enable-clocale=generic --with-libiconv --with-system-zlib --with-build-sysroot=/R/winlibs64_stage/gcc-11.1.0/build_mingw/mingw-w64 CFLAGS=-I/d/Prog/winlibs64_stage/custombuilt/include/libdl-win32
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 11.1.0 (MinGW-W64 x86_64-posix-seh, built by Brecht Sanders)

I tried tdm64 and it worked correctly without issues, like this:

import os

proc threadFunc {.thread.} =
  echo "From thread"

var myThread: Thread[void]
createThread(myThread, threadFunc)
sleep(500)

Compiles and prints "From thread"

Going back to the gcc which is broken, compiling with nim --threads:on --tlsEmulation:on --listCmd --cc:env -f r hello.nim

Works! With the CC environment variable being

echo %CC%
C:\Users\Cameron\.nimble\bin\gcc.exe

Without --tlsEmulation:on , it still crashes, so that fixes it.

creikey avatar Apr 15 '22 01:04 creikey

Why does tlsEmulation:off break on my config in windows? It seems like it doesn't for others. @xflywind can you try compiling hello world with nim --tlsEmulation:off --threads:on r -f hello.nim , and also where gcc to show where your gcc is from? For now I guess I will use the TDM compiler

creikey avatar Apr 15 '22 05:04 creikey

where gcc
C:\Users\blue\Desktop\exe\mingw64\mingw64\bin\gcc.exe
gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=c:/users/blue/desktop/exe/mingw64/mingw64/bin/../libexec/gcc/x86_64-w64-mingw32/11.1.0/lto-wrapper.exe
OFFLOAD_TARGET_NAMES=nvptx-none
Target: x86_64-w64-mingw32
Configured with: ../configure --prefix=/R/winlibs64_stage/inst_gcc-11.1.0/share/gcc --build=x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --enable-offload-targets=nvptx-none --with-pkgversion='MinGW-W64 x86_64-posix-seh, built by Brecht Sanders' --with-tune=generic --enable-checking=release --enable-threads=posix --disable-sjlj-exceptions --disable-libunwind-exceptions --disable-serial-configure --disable-bootstrap --enable-host-shared --enable-plugin --disable-default-ssp --disable-rpath --enable-libstdcxx-pch --enable-libstdcxx-time=yes --disable-libstdcxx-debug --disable-version-specific-runtime-libs --with-stabs --disable-symvers --enable-languages=c,c++,fortran,lto,objc,obj-c++,d,jit --disable-gold --disable-nls --disable-stage1-checking --disable-win32-registry --disable-multilib --enable-ld --enable-libquadmath --enable-libada --enable-libssp --enable-libstdcxx --enable-lto --enable-fully-dynamic-string --enable-libgomp --enable-graphite --enable-mingw-wildcard --with-mpc=/d/Prog/winlibs64_stage/custombuilt --with-mpfr=/d/Prog/winlibs64_stage/custombuilt --with-gmp=/d/Prog/winlibs64_stage/custombuilt --with-isl=/d/Prog/winlibs64_stage/custombuilt --enable-install-libiberty --enable-__cxa_atexit --without-included-gettext --with-diagnostics-color=auto --enable-clocale=generic --with-libiconv --with-system-zlib --with-build-sysroot=/R/winlibs64_stage/gcc-11.1.0/build_mingw/mingw-w64 CFLAGS=-I/d/Prog/winlibs64_stage/custombuilt/include/libdl-win32
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 11.1.0 (MinGW-W64 x86_64-posix-seh, built by Brecht Sanders)

--tlsEmulation:off/on doesn't affect the threads on my PC.

I use 21H2: 22000.556

ringabout avatar Apr 15 '22 06:04 ringabout

Why does tlsEmulation:off break on my config in windows? It seems like it doesn't for others. @xflywind can you try compiling hello world with nim --tlsEmulation:off --threads:on r -f hello.nim , and also where gcc to show where your gcc is from? For now I guess I will use the TDM compiler

That's a good question. I have no knowledge of how tlsEmulation works to answer you. But as it worked using tdm, I believe the mingw64 that nimble is installing, from winlibs.com, is linking some dll (maybe) that is corrupt.

I once had a big battle with mingw64 from winlibs.com, as it doesn't statically link to glibc (at least when compiling a dll). Until I figured out the problem, when I tested tdm, I wasted almost a week.

You could check between the executable with problem and the executable generated by tdm (which works without problem) the dlls that each one depends on with the Dependency Walker.

Here, unfortunately, on Windows 10, I couldn't reproduce the problem.

rockcavera avatar Apr 15 '22 17:04 rockcavera

@xflywind This isn't the gcc that ships with choosenim right?

creikey avatar Apr 15 '22 22:04 creikey

Yeah, I installed it manually.

ringabout avatar Apr 16 '22 00:04 ringabout

@creikey Hi, is this issue related to libwinthread.dll?

ringabout avatar Aug 10 '22 02:08 ringabout

@creikey Hi, is this issue related to libwinthread.dll?

Yeah, I forgot I opened this issue but I figured out how to fix it for me, I added the bin folder in the choosenim mingw installation with the pthreads dll to my path and everything worked again. Windows is very helpful in not specifying at all what the problem is when you see an error like this. Nim should probably check for existence of the threads dll and warn the user if it can't find it instead of failing like this where it's not obvious what's wrong.

creikey avatar Aug 10 '22 03:08 creikey

This is a showstopper imo https://forum.nim-lang.org/t/9368. Seems to be a regression too?

dom96 avatar Aug 14 '22 17:08 dom96

Seems to be a regression too

After switching to --tlsEmulation:off on windows, Now Nim depends on linwinthread.dll on windows with mingw. The solution is to add mingw/bin to path.

ringabout avatar Aug 15 '22 00:08 ringabout

If we don't want an implicit dependency, maybe we should re-enable --tlsEmulation. #18146 was reopened.

metagn avatar Aug 15 '22 11:08 metagn

If we don't want an implicit dependency, maybe we should re-enable --tlsEmulation. #18146 was reopened.

The problem actually lies with the mingw64 distribution that Nim uses, which prefers to dynamically link certain components. Depending on what you compile, there will even be a dependency on "libgcc_s_seh-1.dll", as that's what the maintainer of winlibs wanted.

I'm not saying that winlibs is wrong, but it's a behavior I don't like.

Edit: The problem has appeared in people who installed Nim with choosenim. Then choosenim should add to the Windows environment variable %PATH% the BIN folder of mingw64.

rockcavera avatar Aug 15 '22 18:08 rockcavera

As @rockcavera mentioned, there are some MinGW distributions that statically link winpthread and other similar libraries, such as https://jmeubank.github.io/tdm-gcc/

Yardanico avatar Aug 15 '22 19:08 Yardanico

Would be awesome for Nim to ship that.

dom96 avatar Aug 15 '22 21:08 dom96

If we don't want an implicit dependency, maybe we should re-enable --tlsEmulation. #18146 was reopened.

The problem actually lies with the mingw64 distribution that Nim uses, which prefers to dynamically link certain components. Depending on what you compile, there will even be a dependency on "libgcc_s_seh-1.dll", as that's what the maintainer of winlibs wanted.

I'm not saying that winlibs is wrong, but it's a behavior I don't like.

Edit: The problem has appeared in people who installed Nim with choosenim. Then choosenim should add to the Windows environment variable %PATH% the BIN folder of mingw64.

oh yeah I just realized the binaries I ship too need those dlls to work, that sucks

creikey avatar Aug 16 '22 01:08 creikey

For what it's worth, choosenim specifically installs everything into ~/.nimble/bin so that you only need to add that to your PATH. Choosenim also installs the DLLs in Nim's dlls.zip file (https://github.com/dom96/choosenim/blob/master/src/choosenimpkg/download.nim#L25) so maybe we should just recreate this zip with the required gcc DLLs? I'd rather avoid having to modify choosenim to extract DLLs from gcc and put them in ~/.nimble/bin if possible.

This is just a workaround though, I don't think it's ideal for all Windows programs to have this runtime dependency. How difficult would it be to statically link this?

dom96 avatar Aug 17 '22 12:08 dom96

I will have a try with https://jmeubank.github.io/tdm-gcc/ which @Yardanico suggests.

ringabout avatar Sep 08 '22 04:09 ringabout