iOS shipping build crashes at std::thread exit

An otherwise vanilla UE Project with the following GameMode code crashes iOS shipping builds:

void ANOGSSDKGameModeBase::StartPlay()
{
std::thread({
std::clog << “THREAD @”
<< FILE << “:” << LINE
<< std::endl;
}).join();
}

call-stack:

0 0x00000001922c74bc in __abort ()
1 0x00000001922c740c in abort ()
2 0x0000000192389944 in free ()
3 0x0000000192417f70 in _pthread_tsd_cleanup ()
4 0x0000000192417ce4 in _pthread_exit ()
5 0x000000019241985c in _pthread_body ()
6 0x0000000192419760 in _pthread_start ()
7 0x0000000192416d94 in thread_start ()

Output:

2017-05-30 11:34:13.096921 NOGSSDK[5085:2258376] [DYMTLInitPlatform] platform initialization successful
2017-05-30 11:34:13.626832 NOGSSDK[5085:2258248] Found ue4commandline.txt file
2017-05-30 11:34:13.627670 NOGSSDK[5085:2258248] Combined iOS Commandline: …/…/…/NOGSSDK/NOGSSDK.uproject /Users/beschulz/Documents/Unreal Projects/NOGSSDK/NOGSSDK.uproject -RunConfig=
========= This app is in LANDSCAPE mode
2017-05-30 11:34:13.975549 NOGSSDK[5085:2258403] Project file not found: …/…/…/NOGSSDK/NOGSSDK.uproject
2017-05-30 11:34:14.458866 NOGSSDK[5085:2258248] Metal GPU Frame Capture Enabled
2017-05-30 11:34:14.459737 NOGSSDK[5085:2258248] Metal API Validation Enabled
2017-05-30 11:34:14.500939 NOGSSDK[5085:2258248] ::: Created a UIView that will support Metal :::
2017-05-30 11:34:15.726559 NOGSSDK[5085:2258403] Initializing ULD Communications in game mode
THREAD @/Users/beschulz/Documents/Unreal Projects/NOGSSDK/Source/NOGSSDK/NOGSSDKGameModeBase.cpp:21
NOGSSDK(5085,0x16e9ff000) malloc: *** error for object 0x108e5e050: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug

Reproduction:

create new vanilla C++ project

  • add the code above to StartPlay of the C++ GameMode
  • Select your GameMode and an empty default level as the startup map/mode in Maps&Modes
  • Set Build configuration to Shipping
  • Set-up iOS signing (a development profile will do!)
  • package for iOS
  • open Intermediate/ProjectFilesIOS/MyProject.xcodeproj
  • Press the play button in Xcode

The project files for reproduction are also attached (click).

Remarks:
The crash does not manifest itself when using a plain pthread, at least not in this exact scenario. It also does not happen in debug builds or when debug symbols are enabled (via patching IOSToolchain.cs). I observed the issue when narrowing down a crash in a somewhat more complex scenario. The crash I narrowed down appears in 4.14, 1.15 and 4.16 - but I’ve only tried the reduced case with 4.16. I’ve noticed, that the stack-size of the game-thread is limited to 1MB in shipping builds while it is 8 MB is testing/debug builds. It does not matter if I log in the thread or not.

There is also this report, that may be related: Crashes on thread exit in shared library built with libc++ - Programming & Scripting - Epic Developer Community Forums

Update: for what it’s worth, I’m using Xcode 8.3.2 on iOS 10.2.1. And the crash occurs with plain pthreads in my unisolated scenario as well.

Yes, it also crashes when I install the .ipa on the device and launch it by touching. Using the xcode project this way is a nice way to start the .ipa on the device while having a debugger attached from the start. The crash has nothing to do with the start method.
Edit: thanks for looking into this!

I’ve never seen anyone trying to open/run the .xcodeproj from inside the Intermediates folder before and I’m not sure if this is something we support even doing. What is supposed to be the point of doing this? Do you still get the crash if you install the game to the iOS device normally?

Thank you for the additional information. I’ve placed a bug report in for the issue which can be found here: UE-45650 You can use the provided link to track the bug’s progress. Unfortunately I can’t think of a workaround at the moment aside from taking out the code causing this.

Have a nice day!

Hi Matthew. Is this bug fixed or still present on engine? I am still using 4.16 version. I have a problem with GameSparks integration because of this bug. Just want to know if it’s worth to do an update.

Hello ,

Yes, this still occurs on 4.17. I just tested it manually to make sure. In most cases, if a bug is marked as backlogged, it likely still occurs in the latest version, although there are a few times where an issue gets fixed inadvertently.

Have a nice day!

Hi Matthew,

can you or the other Epic Engineers suggest a workaround for this problem? We really need to get our SDK working again on iOS.

Best,

Hello

Speaking with the developer who was assigned to this bug report originally, the apparent workaround is to avoid using std::thread. This is more of a bug on Apple’s end from his explanation, mentioning that it uses CFAllocator which we cannot easily override with our setup.

Hello Matthew,

I already tried using pthreads directly, but the same crash occurred. It looks like the engine itself is using FRunnableThreadApple on iOS which is a FRunnableThreadPThread. So I wonder why the engine threads would not crash but a pure pthread (or std::thread) would. Or is it to be expected, that those crash at exit as well?

Best,

As you were said, iOS uses it’s foundation’s allocator (CFAllocator) to allocate the thread memory when you are using the STD::THREAD - which Epic team are (I suppose) unlikely to wrap directly,
take a look at iOS pthread implementation of epic.

I wouldn’t call it an apple bug though since iOS without UE4 supports std::thread and even custom allocators.

However it is best practice to use Epic provided functionality for threading “FRunnableThread”
and let the engine to wrap it with whatever it wants.

Hey

Has this issue been addressed at all? I’m running into this issue with GameSparks right now in version 4.17.

Any more news on this?

There are incompatibilities between std::thread (really all std libs) and our memory allocators. One of our programmers just recently fixed some Fortnite issues by removing std::stringstream usage from a plugin that Fortnite depended upon. It’s possible that replacing the std allocators with implementations that call our allocators might fix the issue, but your best bet is to avoid using std libs in UE4.

Hi, If I use a third party library, such as RakNet which depend on stl, how to make it run on iOS?
modify the library ? can I make it as a static link library to avoid std::allocator overrided by FMemory ?

I am not 100% sure, but making it as a static library will most likely solve it.