I see that your intention was to set mExit to true in System::update. In fact mExit gets set to true. But when the update function returns mExit is overwritten once again with the result of the expression
mExit || !mSystem->update()
The clue is that the mExit variable of this expression has already been evaluated before update() gets called. So the result of the expression is false and mExit is set to false again.
I would recommend that you update the mExit variable only in the System::update() function and rewrite the loop to
while (!mExit)
{
mSystem->update();
::Sleep(500);
}