Looking for pointers on debugging a multi-threading issue

Hi, everyone.

I am continuing to work through the archive while implementing a version of HH for Mac OS X using SFML and LLVM (Clang). I've had a lot of fun recently trying to port changes in days 122-125 (multi-threading). It'd took a bit of reading but I've managed to make my own version.

There is still one issue that I can't figure out. When I compile my code with -O2 optimisation level, everything works OK (or, at least, looks and behaves the same as in Casey's videos). Threads aren't conflicting and processing strings properly, rendering isn't broken. However, when I compile with -O0, everything goes nuts. Here's a short gif that showcases the problem: https://gyazo.com/adcef74e2366f4af5959ea0e5b2a5106

This stuff just happens but itself, I am not pressing anything on the keyboard.

I've played around with the code, trying to comment out thread-related stuff and, apparently, weird things start to happen when I add the following line, two hero avatars appear and start shooting swords:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
struct work_queue_entry_storage
{
    void *UserPointer;
};

struct work_queue
{
    uint32 volatile EntryCompletionCount;
    uint32 volatile NextEntryToDo;
    uint32 volatile EntryCount;

    work_queue_entry_storage Entries[256];
};

...

work_queue Queue = {};


If I comment out the "void *UserPointer;" part, everything's OK. When the whole code related to threads is present, the game behaves as in the gif above.

Here's a complete snippet of thread-related code from my code base: https://gist.github.com/roman-d/8bcf27c41353d4db3eb91ee1ce2957af. I would appreciate some pointers on what could be happening. How does this mess up the behaviour of the program in such strange way?
I don't have much experience with that. But you can try a few things:
- Leave the complete multi-threading code, but use only one thread (only the main thread, don't start another). If the problem persists then it may not be multi-threading related;
- Step in the code to see what causes 2 player to spawn, and what makes them go down right (for example: make sure the input struct doesn't contains garbage);
- In general step in the code to make sure it's doing what you want;
- since commenting the void* line change things, maybe you are casting this void* to the wrong type, making you overflow the array and overwriting in whatever is next in memory.

It's also possible that Casey's code has a bug that didn't show on windows but would appear on Mac OS.

Edited by Simon Anciaux on Reason: Left -> right
Thanks for the ideas. Yes, I've spent some time in the debugger. If the work queue variable definition is present then the game_input input variable gets written full of garbage, this makes several controllers become active and everything goes crazy, probably because the update & render code thinks that multiple controllers are present and starts drawing and animating stuff for each controller, hence multiple players, crazy movement and so on.

There's no multithreading going on, just that single definition with the array of void pointers.

https://gyazo.com/7b37667a1635be98ce0c950c31be8724
The next step would be to make sure that you initialize the game_controller_input to zero on startup. Then put a data breakpoint on the game_controller_input[ 1 ].isConnected to see what part of the program changes that memory.

I can't help you much with data breakpoint (watchpoints ?) in xcode (I'm on windows), but a data breakpoint breaks whenever the specified memory location changes value.
Yes, you were right about the initialisation. Zeroing game_input on startup was correct choice of action. At least it'd fixed the problem. I knew it was something silly.

I am not familiar with the data watchpoints, I'll have to try them out. Btw, I use either console lldb or CLion's debug tools (which are horrible). XCode's too weird for me. Maybe it has better facilities for debugging, but I couldn't get the HH's specific setup with two separate builds of the library and the main executable in one up and running.