Page 1 of 2

Room.GetVariable is randomly null

Posted: 31 Jan 2019, 14:08
by Jochanan
Hi,
i am using extension to access room variables

Code: Select all

       
public static ISFSObject GetGameData(this Room room)
{
    Debug.Assert(MainThreadDispatcher.Instance.IsMainThread);

    var gameDataVar = room.GetVariable("gameData");

    if (gameDataVar == null)
    {
        Debug.LogError("Room " + room.Id + " has no gameData");
    }
    else
    {
        return gameDataVar.GetSFSObjectValue();

    }

    return null;
}


I collect data from room in case of SFSEvent.ROOM_VARIABLES_UPDATE.
Sometimes, the room.GetVariable("gameData"); returns null. I have not found any reason why. I tried to check it using breakpoint inside null check and i have found out, that when i call room.GetVariable("gameData") again, it has the data.

I would expect, that all the data are updated prior SFSEvent.ROOM_VARIABLES_UPDATE event, but it looks otherwise. Do you have any idea how to solve my issue?

Re: Room.GetVariable is randomly null

Posted: 31 Jan 2019, 16:13
by Lapo
Hi,
we have no experience or reports of similar issues. Room Variables are populated as soon as you join the Room in question, after that the variables keep being updated in the client until the player leaves the Room.

I can suggest two scenarios where you could get a NULL value:
1) if you're trying to read the variables before joining the Room.
2) if Room Variables in the Room can be removed and re-created. Since removing a Room Variable requires setting it to NULL, it would make the described problem possible.

Are these issues happening while testing locally? Online? Both?
It would help to find a way to reproduce the case.

Thanks

Re: Room.GetVariable is randomly null

Posted: 12 Apr 2019, 16:33
by Jochanan
I am reading room variables on SFSEvent.ROOM_ADD event.

I have a list of rooms, that i am showing to the user - like how many players are in the room, etc.
Every time SFSEvent.ROOM_ADD event occurs, i am creating a new instance of it.
Problem is, that sometimes, when i am creating the room, i get Room.GetVariable() null during the process.

As i said, i am reading Room.GetVariable() as a reaction of SFSEvent.ROOM_ADD event, which happens before SFSEvent.ROOM_JOIN event

Re: Room.GetVariable is randomly null

Posted: 12 Apr 2019, 19:06
by Lapo
Can you send us the steps or a repro-case to reproduce the problem?
Also add the version of SFS2X used, the API platform and version.

Thanks

Re: Room.GetVariable is randomly null

Posted: 13 Apr 2019, 22:05
by Jochanan
This is simplified version.

Code: Select all

Sfs.AddEventListener(SFSEvent.ROOM_JOIN, (evt) => {
    Room room = (Room)evt.Params["room"];
    var gameDataVar = room.GetVariable("gameData");

    if (gameDataVar == null)
    {
        Debug.LogError("Room " + room.Id + " has no gameData");
        return;
    }

    // More code here, when everything is fine
});


Problem may occur in small percentage of cases. (like less than 1%).
Result should be = new room is created and i am joined in that room and i and everyone else has all the data about the room.

Looks like a threading problem to me, but unity uses only one thread... Do you use multiple threads in your API?

2.13.5 + 1.7.8 (last version, that supports .NET 2.0)

Re: Room.GetVariable is randomly null

Posted: 15 Apr 2019, 08:21
by Lapo
Does this happen in the context of the multi-threaded multi-room join that was discussed in another post?
Thanks

Re: Room.GetVariable is randomly null

Posted: 15 Apr 2019, 11:30
by Jochanan
No, sequential request-response create & join room

Re: Room.GetVariable is randomly null

Posted: 15 Apr 2019, 19:30
by Lapo
Ok, thanks.
Are you running the code in Unity? Or is it a C# standalone project?
Do you change the setting of the SmartFox.ThreadSafeMode property in your code?

Thanks

Re: Room.GetVariable is randomly null

Posted: 15 Apr 2019, 20:00
by Jochanan
Lapo wrote:Are you running the code in Unity? Or is it a C# standalone project?

Unity
Lapo wrote:
Do you change the setting of the SmartFox.ThreadSafeMode property in your code?

It is set to true:

Code: Select all

// Set ThreadSafeMode explicitly, or Windows Store builds will get a wrong default value (false)
Sfs.ThreadSafeMode = true;

Re: Room.GetVariable is randomly null

Posted: 16 Apr 2019, 09:03
by Lapo
We need some clarification.
In the first post you said the problem was in the SFSEvent.ROOM_VARIABLES_UPDATE
In the second post you said the problem was in SFSEvent.ROOM_ADD and ROOM_JOIN
In the third post you only mentioned SFSEvent.ROOM_JOIN

These are all different scenarios and it's making things more confusing.

1) ROOM_VARIABLES_UPDATE is only fired after you have joined a Room
2) ROOM_ADD is fired when a Room is added in the Zone but it doesn't provide all the RoomVariables, only those marked as global. To be able to see all the variables you must be joined in the Room.
3) ROOM_JOIN provides with the initial state of the RoomVars when you join a certain Room.

Since you mentioned ROOM_JOIN two times and provided and example of the code you're using, I'd like to start with this one.
When you join a Room you're provided all the variables for that Room.
If you expect a variable X to exist in that Room you should find it 100% of the times, unless there's something else going on.

For starters I would suggest to double-check via the AdminTool > Zone Monitor that a variable really exists when you find a null from the client side.

Second, you have to keep in account that if other calls are concurrently modifying those variables (i.e. deleting them) it is possible that you will find the new state (== deleted) instead of the previous state (== variable exists)

Let us know

Re: Room.GetVariable is randomly null

Posted: 16 Apr 2019, 10:10
by Jochanan
When i wrote the first post, i was not sure, what is the cause of the issue, now i know. At least you can see, for how i am fighting this bug.

So, problem occurs, when i read the variables in SFSEvent.ROOM_ADD, as it is in the code snippet i sent you. That is it.

So, from the client (my unity application using SFS client dll) perspective
1. SFSEvent.ROOM_ADD is fired
2. room.GetVariable("gameData") returns NULL
3. SFSEvent.ROOM_JOIN is fired

Data is not changed on the server side. Data exist. I get null only in about 1/300 cases. I know exactly where the problem is and i know for 100%, that it is in your client api dll. I have spent at lest ten hours to hunt it down, i would really appretiate, if you can focus on your code for once and try to find it as well.

Re: Room.GetVariable is randomly null

Posted: 16 Apr 2019, 14:51
by Lapo
Jochanan wrote:When i wrote the first post, i was not sure, what is the cause of the issue, now i know. At least you can see, for how i am fighting this bug.

So, problem occurs, when i read the variables in SFSEvent.ROOM_ADD, as it is in the code snippet i sent you. That is it.

So, from the client (my unity application using SFS client dll) perspective
1. SFSEvent.ROOM_ADD is fired
2. room.GetVariable("gameData") returns NULL
3. SFSEvent.ROOM_JOIN is fired

I think that's the problem. As I mentioned it's not correct to access variables in the ROOM_ADD event because this not were you expect them. Unless we're talking about global variables.

You should use the ROOM_JOIN event instead, which happens when the user finally has joined the Room and has full access to all variables.

Hope it helps

Re: Room.GetVariable is randomly null

Posted: 16 Apr 2019, 15:04
by Jochanan
Lapo wrote:I think that's the problem. As I mentioned it's not correct to access variables in the ROOM_ADD event because this not were you expect them. Unless we're talking about global variables.

You should use the ROOM_JOIN event instead, which happens when the user finally has joined the Room and has full access to all variables.

Hope it helps


Variables are already there. That are variables, that SERVER inserts into room when it is created. We are talking about global variables.

Because they are global variables and they should be accesible on ROOM_ADD event, you could skip this use case solving.
For a second, lets think about solution you propose, because i love your creativity of outsourcing.
Tell me, how would other users get information about that room, that they are not joining it?
Lets imagine, that you have a server, which provides various games (chess, checkers, tic tac toe) and their variantions (finish rules, danish rules, american rules)
Imagine, you have 1000 users in the lobby and one of them is creating a new game room. The information about the type of game and set of rules is stored inside room variable. So how would other 999 users get the information about the rules and game type of the newly created room - they cannot use ROOM_ADD event, as you suggested before.


I am looking forward hearing from you soon.

Re: Room.GetVariable is randomly null

Posted: 16 Apr 2019, 16:31
by Lapo
If you're expecting global variables to be non null I would recommend to check them with the AdminTool when the problem occurs.
Just to make sure that at least on the server side these variables are non-null.
Also when this happens you can capture the client side debug log and maybe post it here, so we can take a look at the exchange between client server.

I would also suggest to check the server side logs when this happens, to see if any exception might have caused the problem.

Ultimately we will need a proof of concept that demonstrates the issue, so that we can investigate it.

Thanks
p.s. = I don't understand what is the 2nd block of text you quoted. Whose message are you quoting?

Re: Room.GetVariable is randomly null

Posted: 16 Apr 2019, 17:10
by Jochanan
If you're expecting global variables to be non null I would recommend to check them with the AdminTool when the problem occurs.

Already done during several hours of investigation this bug.

Just to make sure that at least on the server side these variables are non-null.

Already done during several hours of investigation this bug.

I would also suggest to check the server side logs when this happens, to see if any exception might have caused the problem.

No exception whatsoever.

Ultimately we will need a proof of concept that demonstrates the issue, so that we can investigate it.


Lets save same time, shall we? I will make several assumptions and if all of them is correct, you should be able to identify the issue yourself

1. Client api is multithreaded
2. There is a thread, that receives events from server and another one, which fires events for the client itself
3. During ROOM_ADD and ROOM_JOIN, you are setting the room variables
4. Room variables are implemented via dictionary
5. Dictionaries are not thread safe

If all of these point are valid (and i know they are), that these chan of events are causing the problem
1. thread for processing server events set ups room, set ups global room variables and enqueue the ROOM_ADD event
2. out application calls ProcessEvents, which pick up the ROOM_ADD event from the queue
3. thread processing server events receives join room event from the server, during that (before ROOM_JOIN is fired), it set ups global variables
4. in the meantime, application runs ROOM_ADD handler and checks the room variables

In case, that during setting up room variables (during FnJoinRoom) is thread paused, and our handler goes live, it returns null - because Dictionary is not thread safe.

Code: Select all

    public void Merge(...)
    {
      ...
      // problem is HERE, because dictionary is not thread safe
      this.variables[variable.Name] = variable;
    }


If the code above represents a code you are using (i cannot know that, but i assume that), that the problem is in that line of code.

I am looking forward to hearing from you soon

PS: In previous post quote, i have just described, why we need to read the global room variable inside ROOM_ADD event