0

I noticed that unless I use something like a Sleep(1) inside of my while loop, it will never break.

while (*Ns::Gl::G == nullptr) Sleep(1); // Works

while (*Ns::Gl::G == nullptr); // Doesn't work

After some research I would think it's because *Ns::Gl::G is changed by another thread or process, this seems likely in my scenario.

So, I tried to do something amongst the lines of:

while (*(volatile TYPE **)&*Ns::Gl::G == nullptr); amongst a lot of other variants of that, and all to no avail.

The way Ns::Gl::G is defined is amongst the lines of:

namespace Ns { struct Gl final { static TYPE** G }; TYPE** Gl::G;}

Does anyone have an idea of how I can turn *Ns::Gl::G into volatile inside of the while loop? MemoryBarrier() works but I'd highly prefer to use the volatile keyword.

TL;DR - volatile cast inside of while loop isn't working.

KaekeaSchmear
  • 1,548
  • 5
  • 18
  • 30
  • 4
    `volatile` doesn't protect you at all, it's not what the keyword is for. Please pick a language, C or C++ so we can give an appropriate answer on how to protect from race conditions. – Hatted Rooster May 27 '19 at 17:21
  • 1
    Highly related: [When to use volatile with multi threading?](https://stackoverflow.com/questions/4557979/when-to-use-volatile-with-multi-threading) – πάντα ῥεῖ May 27 '19 at 17:25
  • @SombreroChicken This isn't a race condition. I'm waiting for `*Ns::Gl::G` to not be a null pointer, but this never happens, unless I add a sleep due to compiler optimizations. Anyway, either language is fine. – KaekeaSchmear May 27 '19 at 17:27
  • 3
    @KaekeaSchmear: If some other thread is changing `G`'s value, then that *is a race condition*. What is responsible for changing `G`'s value? – Nicol Bolas May 27 '19 at 17:28
  • 1
    @KaekeaSchmear If it's another thread that's changing that value then that's literally a race condition. – Hatted Rooster May 27 '19 at 17:29
  • @NicolBolas A thread inside of a process which I injected myself into. – KaekeaSchmear May 27 '19 at 17:32
  • 2
    @KaekeaSchmear: Then whatever thread is writing the variable needs to synchronize with your attempts to read it. Since you're using injection rather than a cooperative interface, it's likely the writing thread does not expect another thread to be reading it, so no synchronization happens. And therefore, there is no way (within the C++ standard) to ensure the order or visibility of that value. So you'd have to rely on out-of-standard mechanisms, like the side-effects of a full memory barrier (such as you might get out of `Sleep`). – Nicol Bolas May 27 '19 at 17:34
  • 1
    @KaekeaSchmear: This is not specifically about "compiler optimizations". The CPU's cache architecture must also be appeased. And, as explained in the duplicate, `volatile` does not. – Nicol Bolas May 27 '19 at 17:35
  • @KaekeaSchmear Maybe a `yield();` call after checking would be enough than the `Sleep();`. – πάντα ῥεῖ May 27 '19 at 17:38
  • @NicolBolas I see, that indeed seems to be the case. Thank you! – KaekeaSchmear May 27 '19 at 17:41
  • @KaekeaSchmear Yes, you have a [data race](https://timsong-cpp.github.io/cppwp/intro.races) even if it doesn't look like a traditional race. Any time you evaluate something that is also being written to by another thread without synchronization, you have a race condition. Race conditions are not limited to when two threads literally race, where the order they finish matters. You have to synchronize your pointer, anything less is Undefined Behavior and any other fix is a bandaid for your symptoms, and bandaids don't stick well to UB. – François Andrieux May 27 '19 at 17:41
  • @πάντα ῥεῖ `Yield()` doesn't seem to work unfortunately. I'd like a prettier solution than `Sleep()` but oh well.. – KaekeaSchmear May 27 '19 at 17:44
  • 1
    @KaekeaSchmear Since you don't have any control over the hooked process, and access any memory synchronizarion from it, I am afraid you'll need to stick with the _ugly_ `Sleep()` call. Maybe there's some WinAPI trickery to apply _change watchers_ for specific process addresses, I am not aware so far. – πάντα ῥεῖ May 27 '19 at 17:50
  • C++ cannot be learned by *guessing*. You should read [a good book](https://stackoverflow.com/q/388242/5910058) or two. – Jesper Juhl May 27 '19 at 19:47
  • @πάντα ῥεῖ So it seems. Thank you so much! – KaekeaSchmear May 27 '19 at 20:32

0 Answers0