The MinGW-w64 toolchain links executables to the old msvcrt C Runtime Library that does not support the x
modifier for the _wfopen()
function.
Fixes #29014.
x
modifier in fsbridge::fopen
call for MinGW builds
#29357
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
For detailed information about the code coverage, see the test coverage report.
See the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.
However, the latter is available on Windows 10 only, which breaks our release compatibility with the older Windows versions.
No? According to the link you provided:
The Universal CRT is a component of the Windows operating system. It is included as a part of Windows 10, starting with the January Technical Preview, and it is available for older versions of the operating system via Windows Update.
Nevertheless, the second commit introduces an assertion in the AutoFile constructor.
Can you explain why this change makes sense? AutoFile
already checks for nullptr.
Nevertheless, the second commit introduces an assertion in the AutoFile constructor.
Can you explain why this change makes sense?
AutoFile
already checks for nullptr.
The added assertion makes the issue with the unsupported x
modifier explicit:
The
streams_tests/xor_file
test will fail without the first commit.
It is already explicit and will fail on master without the first commit:
0unknown location(0): fatal error: in "streams_tests/xor_file": std::ios_base::failure[abi:cxx11]: AutoFile::write: file handle is nullptr: iostream error
🚧 At least one of the CI tasks failed. Make sure to run all tests locally, according to the documentation.
Possibly this is due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.
Leave a comment here, if you need help tracking down a confusing failure.
Concept NACK. I don’t think we should remove test coverage from all other platforms, just to accomodate Windows.
It is not about Windows as a platform. It is about Windows users who download the Bitcoin Core release binaries. We should not treat them in a discriminatory way.
UPD. There are no cases where the “wbx” mode is used in the non-testing code, right?
It is already explicit and will fail on master without the first commit:
0unknown location(0): fatal error: in "streams_tests/xor_file": std::ios_base::failure[abi:cxx11]: AutoFile::write: file handle is nullptr: iostream error
On the master branch the test passes on my system (Ubuntu 22.04):
0$ ./src/test/test_bitcoin.exe -t streams_tests/xor_file
1Running 1 test case...
200f0:err:msvcrt:msvcrt_get_flags incorrect mode flag: x
3
4*** No errors detected
It is already explicit and will fail on master without the first commit:
0unknown location(0): fatal error: in "streams_tests/xor_file": std::ios_base::failure[abi:cxx11]: AutoFile::write: file handle is nullptr: iostream error
On the master branch the test passes on my system (Ubuntu 22.04):
0$ ./src/test/test_bitcoin.exe -t streams_tests/xor_file 1Running 1 test case... 200f0:err:msvcrt:msvcrt_get_flags incorrect mode flag: x 3 4*** No errors detected
Can you add exact steps to reproduce? How is it possible that the file is a nullptr and the std::fwrite
succeeds?
We should not treat them in a discriminatory way.
I don’t see how fixing the tests in the way I’ve suggested would be discriminatory. It would make them work on Windows while retaining the current test for all other platforms.
Can you add exact steps to reproduce?
0$ cat /etc/os-release | head -1
1PRETTY_NAME="Ubuntu 22.04.3 LTS"
2$ x86_64-w64-mingw32-g++-posix --version
3x86_64-w64-mingw32-g++-posix (GCC) 10-posix 20220113
4Copyright (C) 2020 Free Software Foundation, Inc.
5This is free software; see the source for copying conditions. There is NO
6warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7
8$ make -C depends -j $(nproc) HOST=x86_64-w64-mingw32 NO_QT=1
9$ ./autogen.sh && ./configure CONFIG_SITE=$PWD/depends/x86_64-w64-mingw32/share/config.site
10$ make -j $(nproc) -C src test/test_bitcoin.exe
11$ ./src/test/test_bitcoin.exe -t streams_tests/xor_file
12Running 1 test case...
1300f0:err:msvcrt:msvcrt_get_flags incorrect mode flag: x
14
15*** No errors detected
We should not treat them in a discriminatory way.
I don’t see how fixing the tests in the way I’ve suggested would be discriminatory. It would make them work on Windows while retaining the current test for all other platforms.
Thank you! Your suggestion has been implemented.
Can you add exact steps to reproduce?
0$ cat /etc/os-release | head -1 1PRETTY_NAME="Ubuntu 22.04.3 LTS" 2$ x86_64-w64-mingw32-g++-posix --version 3x86_64-w64-mingw32-g++-posix (GCC) 10-posix 20220113 4Copyright (C) 2020 Free Software Foundation, Inc. 5This is free software; see the source for copying conditions. There is NO 6warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 7 8$ make -C depends -j $(nproc) HOST=x86_64-w64-mingw32 NO_QT=1 9$ ./autogen.sh && ./configure CONFIG_SITE=$PWD/depends/x86_64-w64-mingw32/share/config.site 10$ make -j $(nproc) -C src test/test_bitcoin.exe 11$ ./src/test/test_bitcoin.exe -t streams_tests/xor_file 12Running 1 test case... 1300f0:err:msvcrt:msvcrt_get_flags incorrect mode flag: x 14 15*** No errors detected
It prints “No errors detected”, which means that the test passed.
I also tried this locally, and the file is not a nullptr.
I also tried this locally, and the file is not a nullptr.
I agree. That is how it works on Linux in the Wine environment.
On Windows, being linked to msvcrt.dll
, it fails.
I also tried this locally, and the file is not a nullptr.
I agree. That is how it works on Linux in the Wine environment.
On Windows, being linked to
msvcrt.dll
, it fails.
Yes, either the file is a nullptr, in which case the test already fails, or it is not, in which case the test passes. In any case, the added assert in the dropped commit isn’t needed here or elsewhere, and doesn’t change the outcome here.
I also tried this locally, and the file is not a nullptr.
I agree. That is how it works on Linux in the Wine environment. On Windows, being linked to
msvcrt.dll
, it fails.Yes, either the file is a nullptr, in which case the test already fails, or it is not, in which case the test passes. In any case, the added assert in the dropped commit isn’t needed here or elsewhere, and doesn’t change the outcome here.
You are right. That commit was my mistake.
FWIW, the _wfopen_s
function reports an error for the x
modifier even in Wine.
34+ // The MinGW-w64 toolchain links executables to the old msvcrt C Runtime
35+ // Library that does not support the `x` modifier for the _wfopen()
36+ // function. It is possible to link to the new UCRT library instead.
37+ // However, the most easiest way to do it is to use a new GCC with
38+ // the -mcrtdll=ucrt option, which has been available since the commit
39+ // https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=453cb585f0f8673a5d69d1b420ffd4b3f53aca00
Our usage of mingw-w64 and the msvcrt runtime does not support the x modifier for the _wfopen()
. The other info seems a bit overkiil, I’m also not sure if it’s correct. From a quick look, if you choose the runtime you want, when you compile mingw-w64, there’s no need for any GCC flag.
The other info seems a bit overkiil, I’m also not sure if it’s correct. From a quick look, if you choose the runtime you want, when you compile mingw-w64, there’s no need for any GCC flag.
If the new runtime can be linked in guix builds, I’d say it would be better to use it, instead of patching the code. Or is there some downside I am missing?
If the new runtime is available in guix, I’d say it would be better to just use it, instead of patching the code. Or is there some downside I am missing?
I agree that we should move to the new runtime. I assume the downside is possibly dropping support for Windows 7, but I don’t see why that would be a problem.
if you choose the runtime you want, when you compile mingw-w64
Yes, there is --with-default-msvcrt=ucrt
configuration option.
The following patch
0--- a/contrib/guix/manifest.scm
1+++ b/contrib/guix/manifest.scm
2@@ -108,6 +108,16 @@ desirable for building Bitcoin Core release binaries."
3 base-libc
4 base-gcc))
5
6+
7+(define-public mingw-w64-x86_64-winpthreads-ucrt
8+ (package
9+ (inherit mingw-w64-x86_64-winpthreads)
10+ (arguments
11+ (substitute-keyword-arguments (package-arguments mingw-w64-x86_64-winpthreads)
12+ ((#:configure-flags flags)
13+ `(append ,flags
14+ '("--with-default-msvcrt=ucrt")))))))
15+
16 (define (gcc-mingw-patches gcc)
17 (package-with-extra-patches gcc
18 (search-our-patches "gcc-remap-guix-store.patch"
19@@ -116,7 +126,7 @@ desirable for building Bitcoin Core release binaries."
20 (define (make-mingw-pthreads-cross-toolchain target)
21 "Create a cross-compilation toolchain package for TARGET"
22 (let* ((xbinutils (cross-binutils target))
23- (pthreads-xlibc mingw-w64-x86_64-winpthreads)
24+ (pthreads-xlibc mingw-w64-x86_64-winpthreads-ucrt)
25 (pthreads-xgcc (cross-gcc target
26 #:xgcc (gcc-mingw-patches mingw-w64-base-gcc)
27 #:xbinutils xbinutils
results in an error:
0x86_64-w64-mingw32-ld: src/.libs/libwinpthread_la-thread.o: in function `pthread_create_wrapper':
1/tmp/guix-build-mingw-w64-x86_64-winpthreads-11.0.1.drv-0/mingw-w64-v11.0.1/mingw-w64-libraries/winpthreads/src/thread.c:1518: undefined reference to `__intrinsic_setjmpex'
2collect2: error: ld returned 1 exit status
Any ideas how to resolve it?
FWIW, the _wfopen_s function reports an error for the x modifier even in Wine.
So it reports an error but the unit tests don’t fail? Is this another (different bug)?
We use the _wfopen
. Microsoft docs suggest:
More-secure versions of these functions that perform more parameter validation and return error codes are available; see fopen_s, _wfopen_s.
So, the _wfopen_s
is an alternative, which is not used now.
UPD. I’ve made a notice about a potential code change.
I haven’t reviewed this in detail, but it seems good enough for a temporary workaround.
lgtm ACK d4690e449ae470b8274176396564237ee6ec0f35
The MinGW-w64 toolchain links executables to the old msvcrt C Runtime
Library that does not support the `x` modifier for the _wfopen()
function.
I think the documentation should still be adjusted (#29357 (comment)).
Sorry, it skipped my attention. Fixed now.
post-merge ACK d2fe90571e98e02617682561ea82acb1e2647827
I’ve tested this fix earlier on the related issue but missed the PR.