v27 and above - MultiPlayer Bug/Crashes report thread

Joined
Jul 5, 2004
Messages
23,562
Location
Canberra, Australia
Please report all bugs and crashes from the release of v27 and after in this thread.

When posting a an OOS, a bug or a crash please include
The version of C2C you are using;

The logs from all computers (especially the OoS log in the BtS exe folder and the random log in the normal Civ Logs folder).​
 
Very, very early in the game (37,750 BC) and I'm seeing a pretty massive number of animals throughout the world. I'd say 65-70% (if not more) of the non mountain hexes contain an animal. Is this the desired spawn rate?

Huge Perfect Mongoose Snail pace game.
 
Ok, I tried commenting out the caching in CvCity and, testing that dll, we got these OOS Reports. They begin as soon as we go to the next turn.
 
V27 Vanilla
I start a custom game, and I dont have the option for medieval corporation (guilds)
The new Leaders are not in alphabetical order

And... this bad start... (barbarian world on)
 

Attachments

  • badstart.jpg
    badstart.jpg
    127.7 KB · Views: 107
V27 Vanilla
I start a custom game, and I dont have the option for medieval corporation (guilds)
The new Leaders are not in alphabetical order

And... this bad start... (barbarian world on)

Medieval Corporations (guilds) have been replaced with semi-wonders.

Yep that is the sort of bad start you can get with barbarian world on. ;)
 
Sometimes, landmark disappear.... If I put my mouse on the tile, I see it in the detal, but I cant see them on the map

EDIT
And nearly no animal on my island...
What animals can spawn in oceanian with lot of tundra/permafrost/ice and hill? An just find a platypus. On only one (I m turn 215)
 
Ok, I tried commenting out the caching in CvCity and, testing that dll, we got these OOS Reports. They begin as soon as we go to the next turn.
The root causes are likely the same as they used to be. Something in AI_bestUnitAI or one of the functions it calls is not deterministic, probably a part dealing with properties.
At least we know now that it is not that cache that causes the issue.
 
Sometimes, landmark disappear.... If I put my mouse on the tile, I see it in the detal, but I cant see them on the map

EDIT
And nearly no animal on my island...
What animals can spawn in oceanian with lot of tundra/permafrost/ice and hill? An just find a platypus. On only one (I m turn 215)

V27 Vanilla
I start a custom game, and I dont have the option for medieval corporation (guilds)
The new Leaders are not in alphabetical order

And... this bad start... (barbarian world on)

Very, very early in the game (37,750 BC) and I'm seeing a pretty massive number of animals throughout the world. I'd say 65-70% (if not more) of the non mountain hexes contain an animal. Is this the desired spawn rate?

Huge Perfect Mongoose Snail pace game.

*ahem* this is the Multi-Player bugs/crashes thread. For other crashes please post to the stickied Single-Player bugs/crashes thread.
 
Yup, sorry. It was late and I wanted to post that before going to bed.
 
The promotion "flaming arrows II" does nothing
 
A few more OOS logs to look at after my failed attempted fix.

I said:
I recalled Koshling saying the previous fix he'd implemented was necessary due to bAsync not being defined properly so I looked into how bAsync was getting its definitions and in almost every case it appeared that it was only gaining any definition by picking up a false default (and never being evaluated anywhere along the line.) Our test did not find the change to be problematic other than being a failure so I wanted to leave the changes in for review by Koshling and AIAndy to see if the problem is simply that I did not know how to properly define whether the bool should be true or not.
 
A few more OOS logs to look at after my failed attempted fix.
After your test showed that the cache was not to blame it was clear that that would not help.

I have thought about it in the meantime and I think I will add a logging mechanism with message based comparison (because it would be infeasible as file log) to catch the issue as early as possible and get the parameter information.
That will likely still cause a serious slowdown from the huge amount of messages but it should be fine in a local network (and this would only be a special debug mode that you activate to find specific OOS issues).
 
After your test showed that the cache was not to blame it was clear that that would not help.

I have thought about it in the meantime and I think I will add a logging mechanism with message based comparison (because it would be infeasible as file log) to catch the issue as early as possible and get the parameter information.
That will likely still cause a serious slowdown from the huge amount of messages but it should be fine in a local network (and this would only be a special debug mode that you activate to find specific OOS issues).

Ok. Well... tell me this. How would the bAsync variable commonly utilized be determined? How can we ask the game, in code, if we're playing in a multi-player setting at all?

There seemed to be nowhere (except in one case) where this variable was getting any evaluation whatsoever aside from a default false. The random call that seemed to be sending out of sync according to some of the random logs (not saying it couldn't have already been out of sync once it got there) appeared to be suffering from never taking on definition beyond the default parameter definition in the .h file.
 
Ok. Well... tell me this. How would the bAsync variable commonly utilized be determined? How can we ask the game, in code, if we're playing in a multi-player setting at all?
There are few cases where you actually want to ask if it is multiplayer simultaneous turns. Mainly when you actually want something to work different in multiplayer.
Civ4 always uses messages, regardless of if it is single or multiplayer.
bAsync is used in those functions that are called both in a sync and an async context and either use a random value or have possible side effects.
For example evaluating building value is done a lot in the AI, which is a sync context, but it is also used to give a recommendation to the player in the build popup, which is async. In both cases a different RNG needs to be used and the value in the async context must not be added to the cache.

There seemed to be nowhere (except in one case) where this variable was getting any evaluation whatsoever aside from a default false. The random call that seemed to be sending out of sync according to some of the random logs (not saying it couldn't have already been out of sync once it got there) appeared to be suffering from never taking on definition beyond the default parameter definition in the .h file.
In this case the random log only tells you at what point it definitely was out of sync but as this varies, the culprit is earlier and causes some ifs to be traversed differently.
The rest of the sentence I am not quite sure what you are saying.
 
From the changes you made I think there is a misconception here.
If something is async or not is NOT determined by if it is a human player or an AI or if it is multiplayer or singleplayer. Instead it is always determined by where the "thread" starts from (with the exception that you can turn a part of synced code into asynced code by using getActivePlayer).

Examples of synced "thread" entry points:
CvGame::update (the major synced entry point into the DLL that is called once per time slice)
Message executions (the way to get from async code to sync code are messages)

Examples of async entry points:
Code to draw screens or popups
Callbacks from UI widgets

You could go through all functions in both C++ and Python and mark them as either of those:
  • Always async (the function is always called in async context and will cause OOS when called synced)
  • Always synced (the function is always called in synced context and will cause OOS when called async)
  • Uses bAsync (the function is called in both async and synced context and the current context needs to be passed correctly to bAsync)
  • Deterministic (the result of the function only depends on its parameters and when it is called without any side effects on synced data; it can still use a cache but its results need to be the same as the calculation at all times)
 
and the current context needs to be passed correctly to bAsync

This here is what I was trying to get it to do. I attempted to follow the processing to see where many uses of bAsync were getting an assigned value. In almost all uses of the boolean, I was finding there was never any coding to assign a value to bAsync other than passing it along as a default false value in the function declaration. Thus, it did not seem like it could possibly work as intended as bAsync would thus only EVER be showing up as false in these cases.

I admit that I doubted that I was going about it correctly, but since the only example I found of bAsync ever being assigned a non-default 'false' value involved checking whether the currently active player was human or a part of a team with a human player on it, I attempted to see if it was simply lacking this check in all other uses of bAsync. I wanted to share my changes with you (and perhaps they should've been commented out to do so) so that I could show you what I meant if you followed the processing routines.

NEVER in any of these does bAsync ever even get an opportunity to be declared true so it casts doubt on the legitimacy of even utilizing any different approach between an async method and a sync'd method. If my theory was correct, and this was indeed a problem, it would explain a lot since known problem spots were relying on bAsync turning up as true to process in a manner that wouldn't present an OOS error. Since bAsync never had any coding to give it an opportunity to become true, of course it would always register as false since it had been passed as a meaningless parameter with a false default setting to get to the function where we could be having troubles.

Obviously, checking whether the active player is human or part of a team with a human on it was not a solution for correctly defining bAsync. So how does this boolean EVER register as true? And why is this evaluation the ONLY place in the code that ever potentially assigns a non-false value to bAsync?

BTW, I'll reverse my changes, yes. It was only meant to be left there temporarily to see if you could make anything of what I was perceiving as a potential problem there.

Also... question to clarify something you stated there:
Synchronization as a general issue is only applicable in a simultaneous multiplayer setting so why wouldn't we want the code to simply always act as if its got to behave as if it were async during such gameplay whether it needs to or not? Wouldn't it be safer to go about it like that?


EDIT: after reading and rereading what you posted above, I believe I'm beginning to understand that bAsync is never assigned based on a static status in the game itself so much as an assignment that should be picked up when calling to a function FROM a function that is already running Async. But what I still find odd is that NOWHERE in the dll (with the exception of that one example) is a true value passed to bAsync in a function call where bAsync is a variable. I'm probably pretty useless at determining that a function is supposed to be running in Async context and I still need to understand a lot more about how messages are passed to update each connected computer, how those messages are picked up and how they help the computers 'get back on track' and back into a deterministic state, but doesn't it seem funny that the dll will NEVER utilize the bAsync variable in so many cases where we're attempting to use it to avert a OOS problem? Interestingly too, most of the py files exposing these functions that use the bAsync variable don't seem to offer the bAsync variable for definition either.
 
There is at least one call with bAsync = true in CvDllButtonPopup launchProductionPopup and that might indeed be the only one.

If you just want to show code, make a branch and commit your code to the branch.

Also... question to clarify something you stated there:
Synchronization as a general issue is only applicable in a simultaneous multiplayer setting so why wouldn't we want the code to simply always act as if its got to behave as if it were async during such gameplay whether it needs to or not? Wouldn't it be safer to go about it like that?
It is bad style and you don't gain anything from doing that.
 
Back
Top Bottom