I'm running into an issue where sometimes, a formspec triggered by the server won't become visible on the client because of a race condition when another form is closed about at the same time:
Normally, GUIFormSpecMenu::~GUIFormSpecMenu gets called right after GUIModalMenu::quitMenu, and afterwards, opening a formspec through handleCommand_ShowFormSpec works by creating a new object.
Rarely, handleCommand_ShowFormSpec gets processed after GUIModalMenu::quitMenu but before GUIFormSpecMenu::~GUIFormSpecMenu gets called. In these cases, GUIFormSpecMenu::setFormspecPrepend et al are called on the formspec object which is about to close, and are never seen by the client.
Any ideas? Maybe this processing could be (partially) serialized so a formspec object where the client already knows it will close will not be used to provide new dialogs.
Race condition on closing/reopening formspec
- sorcerykid
- Member
- Posts: 1502
- Joined: Fri Aug 26, 2016 15:36
- GitHub: sorcerykid
- In-game: Nemo
- Location: Illinois, USA
Re: Race condition on closing/reopening formspec
Try doing `minetest.after`with 0s delay, as that will make the new form show one tick after the other one closed.
Re: Race condition on closing/reopening formspec
From what I understand handleCommand_* are executed on packet receive. And Minetest uses UDP, which has no constraint on the order in which the packets are received (to be faster than TCP). If you call minetest.close_formspec("player_name", "my_formspec", formspec) and minetest.open_formspec("player_name", "my_formspec", [other_]formspec) almost at the same time, 2 packets are sent and there is no guaranty that close is executed before open on the client side.
If you are lucky both packets are treated during the same loop and you may check for concurrent packet. If you are not lucky close may be treated during the next loop and there will be no way to know if there was a concurrent packet.
Could you give an example showing when this happens sometime? I suppose it is for updating the currently displayed formspec. There may be other way to do it, like not closing it or using a variable formname according to the content. I don't know, I haven't tested it outside player inventory formspec which has a `set` method.
`doc` from Wuzzy's minetest_doc_modpack updates the currently viewed formspec by never closing it.
Using a timer or after can do the trick almost at all time and virtually solve the issue, but there is logically no guaranty that it works 100% of the time if it is really an UDP packet order issue. If it is not, well, you may discard this post :)
If you are lucky both packets are treated during the same loop and you may check for concurrent packet. If you are not lucky close may be treated during the next loop and there will be no way to know if there was a concurrent packet.
Could you give an example showing when this happens sometime? I suppose it is for updating the currently displayed formspec. There may be other way to do it, like not closing it or using a variable formname according to the content. I don't know, I haven't tested it outside player inventory formspec which has a `set` method.
`doc` from Wuzzy's minetest_doc_modpack updates the currently viewed formspec by never closing it.
Using a timer or after can do the trick almost at all time and virtually solve the issue, but there is logically no guaranty that it works 100% of the time if it is really an UDP packet order issue. If it is not, well, you may discard this post :)
- v-rob
- Developer
- Posts: 816
- Joined: Thu Mar 24, 2016 03:19
- GitHub: v-rob
- IRC: v-rob
- Location: Right behind you.
Re: Race condition on closing/reopening formspec
If this is a problem caused by using minetest.close_formspec followed by minetest.show_formspec to update a form, don't close the formspec at all. minetest.close_formspec should only be used for just that -- closing the formspec. minetest.show_formspec both shows and reshows (updates) a formspec without minetest.close_formspec even necessary.
-
- Member
- Posts: 167
- Joined: Mon May 22, 2017 20:27
Re: Race condition on closing/reopening formspec
As far as I can understand from his description of the problem, I think his issue is either that the client is ignoring a new form from the server if the user happens to close an existing from on the client at the exact same time/within the same client tick, or that the server isn't sending out a new form to the client if the server receives a close event for an existing form from the client at the exact same time/within the same server tick. In either case, using minetest.after won't fix it as there could equally be a race condition in the following tick (if it is indeed a race condition between an action on the server and an independent action on the client/user that the server has no control over).sorcerykid wrote:Try doing `minetest.after`with 0s delay, as that will make the new form show one tick after the other one closed.
-
- Member
- Posts: 167
- Joined: Mon May 22, 2017 20:27
Re: Race condition on closing/reopening formspec
From a quick look at the source code (network/connection.cpp and network/connection.h) combined with my (limited) knowledge of Minetest's networking behavior, I'm fairly certain that Minetest implements its own packet ordering. Otherwise other "glitches" resulting from out-of-order packets (nodes vanishing after being placed, chat messages especially automated ones appearing out of order, etc.) would be common enough that you would hear about it, and even over very laggy and unreliable network connections I have never experienced anything like this myself.karamel wrote:From what I understand handleCommand_* are executed on packet receive. And Minetest uses UDP, which has no constraint on the order in which the packets are received (to be faster than TCP). If you call minetest.close_formspec("player_name", "my_formspec", formspec) and minetest.open_formspec("player_name", "my_formspec", [other_]formspec) almost at the same time, 2 packets are sent and there is no guaranty that close is executed before open on the client side.
If you are lucky both packets are treated during the same loop and you may check for concurrent packet. If you are not lucky close may be treated during the next loop and there will be no way to know if there was a concurrent packet.
Who is online
Users browsing this forum: No registered users and 2 guests