Merge lp:~widelands-dev/widelands/bug-1724145-corrupt-zip-when-saving into lp:widelands

Proposed by GunChleoc
Status: Merged
Merged at revision: 8743
Proposed branch: lp:~widelands-dev/widelands/bug-1724145-corrupt-zip-when-saving
Merge into: lp:widelands
Diff against target: 100 lines (+23/-6)
4 files modified
data/campaigns/emp03.wmf/scripting/mission_thread.lua (+1/-2)
data/campaigns/emp04.wmf/scripting/starting_conditions.lua (+1/-2)
data/campaigns/tutorial04_economy.wmf/scripting/mission_thread.lua (+1/-2)
src/scripting/lua_map.cc (+20/-0)
To merge this branch: bzr merge lp:~widelands-dev/widelands/bug-1724145-corrupt-zip-when-saving
Reviewer Review Type Date Requested Status
Notabilis Approve
Review via email: mp+349087@code.launchpad.net

Commit message

Do not save LuaEconomy objects in Lua scrips for use later

- Due to economy merging, the economy object can become unavailable and cause crashes.
- Fixed Lua scripts and added warnings to documentation.

Description of the change

The underlying economy object can disappear from eco:ware_target_quantity calls due to economy merging. I found no way to check for that in the ware_target_quantity function itself, so I have added warnings to the documentation and fixed the Lua scripts.

To reproduce the Bug:

1. Play Empire 3: Neptune's Revenge until you trigger the "Lower Marble Columns" objective. Do not take any action on the objective.

2. Delete a road so that you end up with 2 economies

3. Connect the outer economy to the Headquarters Shipwreck economy: Pick a flag in the outer economy to start road building, then a flag in the original economy.

To post a comment you must log in.
Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 3635. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/401193955.
Appveyor build 3434. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_bug_1724145_corrupt_zip_when_saving-3434.

Revision history for this message
Notabilis (notabilis27) wrote :

Diff and testing are fine.

Maybe move the warning to the economy class instead of warning at every method? But that would probably increase the risk of overlooking it.

From a brief look at the code I guess one could replace the raw pointer to the economy with a weak_ptr and check it before dereferencing it in the methods. But this would mean quite a lot of refactoring for making all economy references shared_ptr.
Another possibility would be a "economy registration" and, e.g., referencing the economies by id. A list of economies already exists in the class Player but I haven't checked whether a pointer to that class will stay valid if the player is defeated.

review: Approve
Revision history for this message
GunChleoc (gunchleoc) wrote :

The problem is that the method is called on a null object, so I can't do any checks in the method, because it's already too late. I tried checking whether get() is not null, but that doesn't work in the current implementation of the Lua interface. No idea if weak_ptr could help here.

The only way to avoid problems would be to completely remove LuaEconomy and not use it, but using numbers is probably fragile in its own way.

Thanks for the review!

@bunnybot merge

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'data/campaigns/emp03.wmf/scripting/mission_thread.lua'
2--- data/campaigns/emp03.wmf/scripting/mission_thread.lua 2018-01-25 19:28:03 +0000
3+++ data/campaigns/emp03.wmf/scripting/mission_thread.lua 2018-07-07 11:04:51 +0000
4@@ -99,8 +99,7 @@
5 local objective = add_campaign_objective(obj_lower_marble_column_demand)
6
7 --- Check the headquarters' flag's economy
8- local eco = sf.brn.immovable.economy
9- while eco:ware_target_quantity("marble_column") ~= 4 do
10+ while sf.brn.immovable.economy:ware_target_quantity("marble_column") ~= 4 do
11 sleep(2434)
12 end
13 sleep(4000)
14
15=== modified file 'data/campaigns/emp04.wmf/scripting/starting_conditions.lua'
16--- data/campaigns/emp04.wmf/scripting/starting_conditions.lua 2018-05-29 20:14:16 +0000
17+++ data/campaigns/emp04.wmf/scripting/starting_conditions.lua 2018-07-07 11:04:51 +0000
18@@ -20,8 +20,7 @@
19 r4 = p3:place_road(field_mill.immovable.flag, "br", "r", true)
20
21 p3:forbid_buildings("all")
22-local eco = field_warehouse.brn.immovable.economy
23-eco:set_ware_target_quantity("beer", 180)
24+field_warehouse.brn.immovable.economy:set_ware_target_quantity("beer", 180)
25
26 -- =======================================================================
27 -- Player 1
28
29=== modified file 'data/campaigns/tutorial04_economy.wmf/scripting/mission_thread.lua'
30--- data/campaigns/tutorial04_economy.wmf/scripting/mission_thread.lua 2018-05-03 06:01:14 +0000
31+++ data/campaigns/tutorial04_economy.wmf/scripting/mission_thread.lua 2018-07-07 11:04:51 +0000
32@@ -152,8 +152,7 @@
33 message_box_objective(plr, economy_settings2)
34 o = message_box_objective(plr, economy_settings3)
35
36- local eco = sf.brn.immovable.economy
37- while eco:ware_target_quantity("marble_column") ~= 20 do
38+ while sf.brn.immovable.economy:ware_target_quantity("marble_column") ~= 20 do
39 sleep(200)
40 end
41 -- wait that the player has really changed the target quantity
42
43=== modified file 'src/scripting/lua_map.cc'
44--- src/scripting/lua_map.cc 2018-04-27 06:11:05 +0000
45+++ src/scripting/lua_map.cc 2018-07-07 11:04:51 +0000
46@@ -3585,6 +3585,10 @@
47
48 Returns the amount of the given ware that should be kept in stock for this economy.
49
50+ **Warning**: Since economies can disappear when a player merges them
51+ through placing/deleting roads and flags, you must get a fresh economy
52+ object every time you use this function.
53+
54 :arg warename: the name of the ware.
55 :type warename: :class:`string`
56 */
57@@ -3605,6 +3609,10 @@
58
59 Returns the amount of the given worker that should be kept in stock for this economy.
60
61+ **Warning**: Since economies can disappear when a player merges them
62+ through placing/deleting roads and flags, you must get a fresh economy
63+ object every time you use this function.
64+
65 :arg workername: the name of the worker.
66 :type workername: :class:`string`
67 */
68@@ -3625,6 +3633,10 @@
69
70 Sets the amount of the given ware type that should be kept in stock for this economy.
71
72+ **Warning**: Since economies can disappear when a player merges them
73+ through placing/deleting roads and flags, you must get a fresh economy
74+ object every time you use this function.
75+
76 :arg warename: the name of the ware type.
77 :type warename: :class:`string`
78
79@@ -3651,6 +3663,10 @@
80
81 Sets the amount of the given worker type that should be kept in stock for this economy.
82
83+ **Warning**: Since economies can disappear when a player merges them
84+ through placing/deleting roads and flags, you must get a fresh economy
85+ object every time you use this function.
86+
87 :arg workername: the name of the worker type.
88 :type workername: :class:`string`
89
90@@ -4043,6 +4059,10 @@
91
92 (RO) Returns the economy that this flag belongs to.
93
94+ **Warning**: Since economies can disappear when a player merges them
95+ through placing/deleting roads and flags, you must get a fresh economy
96+ object every time you call another function on the resulting economy object.
97+
98 :returns: The :class:`Economy` associated with the flag.
99 */
100 int LuaFlag::get_economy(lua_State* L) {

Subscribers

People subscribed via source and target branches

to status/vote changes: