Sunday, January 21, 2024

Month 2 - Week 2 - GController Bug Investigation

 Last week I spent time correcting and fixing a bug relating to macro usage and the context of what the macros actually represented. I'm happy to say this bug has been fixed and is now merged. Stepping further into GController, however, there are other bugs present that I decided to investigate. Particularly, there is one I noticed that piqued my interest.


I read through this issue and immediately wanted to diagnose it. At hand, the issue is rather simple. If you have a controller already plugged in before the GController is initialized, GController fails to properly "see" it, resulting in inaccurately reported information. For instance, if you were to call the function `GetNumConnected` which returns the total connected controllers, it would return zero instead of one if you had a single controller plugged in before GController is initialized. I decided to make a little unit test that would check for this inaccuracy, and then determine how GController would react. GController initially reported the unit test passing, which didn't sound right. I updated the unit test a little more, this time to provide printouts for the reported number of controllers compared against a manually checked reported number. To my surprise, they both were reporting zero, meaning that GController didn't even register that the controller was there at all.


This misreported number is unsettling, especially because the manual check is supposed to catch the inaccuracy and fail the test. After around two hours of researching, I reran the test, and amazingly, it failed. It worked as expected. The controllers connected reported zero, however, the confirmed controllers connected reported one. So, off the unit test, we have a bug that may or may not show at all. I decided to dig into the code at this point and debug.

From the debugging, I came across code internally that seems to be the problem:


In the initialize function, we see an event callback that is set up for XInput. In this event callback, we can start to piece together how the function is working. We call onto XInput to get the state of each controller slot, if the controller is connected, it will then work on setting up the controller, mapping what's needed, and then revealing it's connected. Something of note is that this code is bug-free. It works as expected, and also detects my controller fine. The problem is it is an event callback. The reason this becomes an issue is simple.

What if, by chance, you initialize GController and test for a controller before the event callback is called? What happens is the bug we're experiencing. This callback is being handled on a separate thread (if my information is correct). So what happens is the code we call and execute is happening too fast, and due to that, XInput hasn't initialized the controllers yet, which results in GController showing that no controller is plugged in. This means one of two things. We either need to initialize the controllers manually before XInput does, or we delay the program long enough for XInput to initialize itself. There is possibly another way, which is initializing XInput, and then calling the callback itself after (this assumes the back-end is created for XInput to allow this), but currently, these are the options left to choose from.

There is no resolution for this issue currently as I'm still working on getting it completed and fixed. From what's inspected though, I have a pretty good idea of what's happening now. So all that is needed is to test more, make changes, and see if this can be corrected.

No comments:

Post a Comment