https://bugs.winehq.org/show_bug.cgi?id=49802
Bug ID: 49802 Summary: Crash at AfxBeginThread of x64 apps on macOS when built with VS2019 Product: Wine Version: 5.16 Hardware: x86-64 OS: Mac OS X Status: UNCONFIRMED Severity: normal Priority: P2 Component: -unknown Assignee: wine-bugs@winehq.org Reporter: reinhold.hoffmann@hotmail.com
Created attachment 68117 --> https://bugs.winehq.org/attachment.cgi?id=68117 Samples to demonstrate the issue
Our x64 apps built with Visual Studio 2010 (VS2010) run on macOS for a long time. We recently have started a project to move to Visual Studion 2019 (VS2019). The same x64 app which works fine when built with VS2010 crashes on macOS when it is built with VS2019. The crash occurs when the MFC function AfxBeginThread is called. Static linking is used for linking the MFC and other libs.
After a very painful research we identified that a simular report has been made in Nov. 2019 in the Wineskin area (see https://github.com/Gcenx/WineskinServer/issues/22).
The reporter said "I ended up replacing the AfxBeginThread call with a call to CreateThread which works fine on all versions." We did the same thing with the same result. Replacing AfxBeginThread by CreateThread works fine with VS2019. However, according to https://stackoverflow.com/questions/21718674/difference-between-afxbeginthre... a replacement of AfxBeginThread by CreateThread is not really recommended when MFC is used.
The crash happens on all macOS versions with Wine 5.4, 5.7 and 5.16 (we took 5.16 from Gcenx (https://github.com/Gcenx/macOS_Wine_builds)). On Windows and Linux the VS2019 app runs fine. Further, the Win32 equivalent app runs fine on macOS.
In summary:
A crash happens for AfxbeginThread in an x64 app on macOS with Wine 5.4, 5.7, 5.16.
We did a deeper dive and found that the crash happens inside AfxbeginThread, module Thread.cpp inside the function __acrt_get_begin_thread_init_policy. See address: 0001:001ab7cc __acrt_get_begin_thread_init_policy 00000001401ac7cc f libucrt:win_policies.obj
According to the backtrace.txt (attached) the exception happens when reading from a 32 bit address. This sounds strange to me for a x64 app.
Any help is highly appreciated.
Reinhold
==========================================================================
As a C++ sample I have compiled a trivial app which AfxBeginThread which demonstrate the problem.
In the attached zip file you can find
backtrace.txt Test_of_AfxBeginThread_VS2019.exe Test_of_AfxBeginThread_VS2010.exe
The code and project files for VS2010 and VS2019 can be downloaded from www.notation.com/download/Wine/Bugzilla/Project_Files_AfxBeginThread_samples.zip
https://bugs.winehq.org/show_bug.cgi?id=49802
--- Comment #1 from Ken Thomases ken@codeweavers.com --- There are currently limitations to how well macOS can support running 64-bit Windows apps.
The root problem is an ABI incompatibility about the use of the %gs register (and the hidden GS.base register). Windows has GS.base point to the TEB. macOS has GS.base point to its pthread thread-local storage (TLS) area. On Linux, GS.base is free for apps to use, so Wine can make it point to the TEB. On macOS, we can't really change GS.base without breaking system libraries.
What 64-bit compatibility we do have for macOS is due to the fact that most Windows programs only access certain fields of the TEB (offsets from GS.base) directly. Wine pokes appropriate values into the pthread TLS area at those offsets so that Windows programs find what they expect. Apple has blessed this approach and reserved those offsets within the TLS area for this purpose.
But for any app which accesses other offsets directly, they get junk. Unfortunately, somewhere within AfxBeginThread() there's just such an access. There's not currently a clean workaround.
https://bugs.winehq.org/show_bug.cgi?id=49802
--- Comment #2 from Reinhold reinhold.hoffmann@hotmail.com --- Thanks for the immediate response. It is very helpful.
With the discussion on stackoverflow (https://stackoverflow.com/questions/53244454/how-did-wine64-manage-to-handle...) the issue is now clearly understood.
Our task now is to find a workaround either - use CreateThread instead of AfxBeginThread because our apps use AfxBeginThread just in few cases, or - stay longer with VS2010
In the future this issue may become a major obstacle because more developments - migrate their apps to x64 - use of latest Visual Studio versions - use Wine primarily for macOS because of the greater prevalence of Mac PCs compared to Linux PCs
I hope that the report here helps others, too.
Thanks again.
https://bugs.winehq.org/show_bug.cgi?id=49802
Fabian Maurer dark.shadow4@web.de changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |dark.shadow4@web.de
https://bugs.winehq.org/show_bug.cgi?id=49802
Reinhold reinhold.hoffmann@hotmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Summary|Crash at AfxBeginThread of |Crashes of x64 apps on |x64 apps on macOS when |macOS when built with |built with VS2019 |VS2019
https://bugs.winehq.org/show_bug.cgi?id=49802
--- Comment #3 from Reinhold reinhold.hoffmann@hotmail.com --- After working on workarounds for this issue with VS2019 it turns out that there is a broader impact than originally thought. I therefore changed the title of this bug report.
The core reasons are that the two function calls ------------------------------------------------ (1) __acrt_get_begin_thread_init_policy in libucrt:win_policies.obj called by thread.cpp as part of ucrt
(2) __acrt_get_process_end_policy in libucrt:win_policies.obj called by exit.cpp as part of ucrt
end in the nowhere according to the comment from Ken Thomases here.
Impact: ------- (1) is used in the function calls "_beginthread" and "_beginthreadex". These functions are called when a thread is started like in AfxBeginThread. Using features from MFC like CMFCMenuBar, CMFCToolBar etc. from MFC of VS2019 x64 use these calls frequently e.g. in AFXPlaySystemSound. This means that apps using CMFCMenuBar, CMFCToolBar etc. from MFC of VS2019 won't run on Wine macOS x64.
(2) is used in the regular call "exit" This means that any regular end of an x64 app which is build with MFC of VS2019 craches on Wine macOS x64. The crash happens either at once or the app ends up in a loop where the app needs to be terminated using the Force Quit command of the Mac.
Possible workarounds with VS2019: (1) when threads are only selectively used with AfxBeginThread, replacing those calls by CreateThread may help but please consider https://stackoverflow.com/questions/21718674/difference-between-afxbeginthre...
(2) Before exiting the x64 app the call TerminateProcess(GetCurrentProcess(), return_code); can help to terminate app without ending in a crash.
https://bugs.winehq.org/show_bug.cgi?id=49802
Brendan Shanks bshanks@codeweavers.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |bshanks@codeweavers.com
https://bugs.winehq.org/show_bug.cgi?id=49802
--- Comment #4 from Brendan Shanks bshanks@codeweavers.com --- I also hit this bug while testing the Chromium Embedded Framework test EXE on macOS, it crashes in __acrt_get_process_end_policy() when quitting the app.
I opened a bug with Microsoft to fix the C runtime, it's a long shot but worth a try. Anyone with a Microsoft account should go over and upvote it.
https://developercommunity.visualstudio.com/content/problem/1248753/64-bit-e...
https://bugs.winehq.org/show_bug.cgi?id=49802
--- Comment #5 from Reinhold reinhold.hoffmann@hotmail.com --- Thx. So, I recommend to change the status from UNCONFIRMED to CONFIRMED
https://bugs.winehq.org/show_bug.cgi?id=49802
--- Comment #6 from Brendan Shanks bshanks@codeweavers.com --- Steve Wishnousky posted on the Microsoft bug report that this issue should be fixed in the next Windows SDK version (presumably the next one released after the current 10.0.22000.0), and also that it should not happen with the older 10.0.14393.0 SDK.
" I’ve recently took another look and it appears an unrelated change has resolved this issue.
Since this is an issue in the Universal C Runtime, updates to the static library are shipped in the Windows SDK and updates to the DLL are delivered via Windows Update in new OS versions. The next major version of the Windows SDK and Windows will contain a Universal C Runtime that does not exhibit this behavior.
Until the new SDK is released, a workaround is to use an older Windows SDK to build with. I believe the 10.0.14393.0 Windows 10 SDK is the most recent SDK without this issue. It looks like this UCRT still references gs:60h, but not in the code path mentioned in the bug report. "
https://bugs.winehq.org/show_bug.cgi?id=49802
--- Comment #7 from Brendan Shanks bshanks@codeweavers.com --- I haven't tested it, but Steve Wishnousky from Microsoft posted that:
Until the next major version of the Windows OS and Windows SDK ships, a fix for this issue is now available in the Windows Insider Preview SDK, available here: https://www.microsoft.com/en-us/software-download/windowsinsiderpreviewSDK.
I assume this is the build 22598 SDK.
https://bugs.winehq.org/show_bug.cgi?id=49802
--- Comment #8 from Reinhold reinhold.hoffmann@hotmail.com --- After deep testing I can confirm that the bug is fixed with Windows SDK 22621. Please find attached Confirmation_bug_fix_49802_with_Windows_SDK_22621.zip which contains exe files built with VS2019 and SDK 22000 and 22621
https://bugs.winehq.org/show_bug.cgi?id=49802
--- Comment #9 from Reinhold reinhold.hoffmann@hotmail.com --- Created attachment 72542 --> https://bugs.winehq.org/attachment.cgi?id=72542 exe files to confirm bug fix
included 2 cpp files and build files with SDK 22000 (which show the bug) and 22621 which are clean