Merge lp:~widelands-dev/widelands/bug-1636966-one-soldier-crash into lp:widelands/build19

Proposed by GunChleoc
Status: Rejected
Rejected by: GunChleoc
Proposed branch: lp:~widelands-dev/widelands/bug-1636966-one-soldier-crash
Merge into: lp:widelands/build19
Diff against target: 100 lines (+22/-16)
1 file modified
src/logic/map_objects/tribes/soldier.cc (+22/-16)
To merge this branch: bzr merge lp:~widelands-dev/widelands/bug-1636966-one-soldier-crash
Reviewer Review Type Date Requested Status
Widelands Developers Pending
Review via email: mp+309445@code.launchpad.net

Commit message

Abort battle if opponent is nullptr to avoid segfaults.

Description of the change

There is no easy way to reproduce this, so I have followed the solution suggested in the bug.

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

Continuous integration builds have changed state:

Travis build 1524. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/171031811.
Appveyor build 1367. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_bug_1636966_one_soldier_crash-1367.

Revision history for this message
SirVer (sirver) wrote :

I feel uneasy getting this into b19.

We do not know what the root cause of the bug is - why the other soldier can be zero. We know it happens - which breaks our codes assumptions already. This branch deals with this unexpected situation, potentially carrying it further and masking more bugs down the line. My argument is that crashing early is way better than hiding further bugs.

A quick qblame showed me that this code was introduced in r5877 in 2011 to fix bug 612348 - to which we also did not have a good understanding it seems. It seems this bug has been around sufficiently long to not warrant this fix for b19.

Agreed?

Revision history for this message
GunChleoc (gunchleoc) wrote :

You have convinced me.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/logic/map_objects/tribes/soldier.cc'
2--- src/logic/map_objects/tribes/soldier.cc 2016-08-04 15:49:05 +0000
3+++ src/logic/map_objects/tribes/soldier.cc 2016-10-27 08:33:31 +0000
4@@ -1253,8 +1253,14 @@
5 }
6
7 Map& map = game.map();
8- Soldier& opponent = *battle_->opponent(*this);
9- if (opponent.get_position() != get_position()) {
10+ Soldier* opponent = battle_->opponent(*this);
11+ // If the opponent disappeared from under us, cancel the battle.
12+ // TODO(GunChleoc): Analyze why the opponent can be nullptr.
13+ if (!opponent) {
14+ battle_->cancel(game, *this);
15+ return;
16+ }
17+ if (opponent->get_position() != get_position()) {
18 if (is_a(Building, map[get_position()].get_immovable())) {
19 // Note that this does not use the "leavebuilding" task,
20 // because that task is geared towards orderly workers leaving
21@@ -1273,19 +1279,19 @@
22 return skip_act(); // we will get a signal via set_battle()
23 } else {
24 if (combat_walking_ != CD_COMBAT_E) {
25- opponent.send_signal(game, "wakeup");
26+ opponent->send_signal(game, "wakeup");
27 return start_task_move_in_battle(game, CD_WALK_E);
28 }
29 }
30 } else {
31- if (opponent.stay_home() && (this == battle_->second())) {
32+ if (opponent->stay_home() && (this == battle_->second())) {
33 // Wait until correct roles are assigned
34 new Battle(game, *battle_->second(), *battle_->first());
35 return schedule_act(game, 10);
36 }
37
38- if (opponent.get_position() != get_position()) {
39- Coords dest = opponent.get_position();
40+ if (opponent->get_position() != get_position()) {
41+ Coords dest = opponent->get_position();
42
43 if (upcast(Building, building, map[dest].get_immovable()))
44 dest = building->base_flag().get_position();
45@@ -1318,8 +1324,8 @@
46 static_cast<unsigned int>(owner().player_number()) % get_position().x %
47 get_position().y %
48 (immovable_position ? immovable_position->descr().descname().c_str() : ("no")) %
49- opponent.descr().descname().c_str() % opponent.serial() %
50- static_cast<unsigned int>(opponent.owner().player_number()) % dest.x % dest.y %
51+ opponent->descr().descname().c_str() % opponent->serial() %
52+ static_cast<unsigned int>(opponent->owner().player_number()) % dest.x % dest.y %
53 (immovable_dest ? immovable_dest->descr().descname().c_str() : ("no")) %
54 descr().descname().c_str())
55 .str();
56@@ -1329,22 +1335,22 @@
57 "images/ui_basic/menu_help.png", _("Logic error"),
58 (boost::format("<rt><p font-size=12>%s</p></rt>") % messagetext).str(),
59 get_position(), serial_));
60- opponent.owner().add_message(
61+ opponent->owner().add_message(
62 game, *new Message(
63 Message::Type::kGameLogic, game.get_gametime(), descr().descname(),
64 "images/ui_basic/menu_help.png", _("Logic error"),
65 (boost::format("<rt><p font-size=12>%s</p></rt>") % messagetext).str(),
66- opponent.get_position(), serial_));
67+ opponent->get_position(), serial_));
68 game.game_controller()->set_desired_speed(0);
69 return pop_task(game);
70 }
71 }
72 } else {
73- assert(opponent.get_position() == get_position());
74- assert(battle_ == opponent.get_battle());
75+ assert(opponent->get_position() == get_position());
76+ assert(battle_ == opponent->get_battle());
77
78- if (opponent.is_walking()) {
79- molog("[battle]: Opponent '%d' is walking, sleeping\n", opponent.serial());
80+ if (opponent->is_walking()) {
81+ molog("[battle]: Opponent '%d' is walking, sleeping\n", opponent->serial());
82 // We should be woken up by our opponent, but add a timeout anyway for robustness
83 return start_task_idle(game, descr().get_animation("idle"), 5000);
84 }
85@@ -1352,13 +1358,13 @@
86 if (battle_->first()->serial() == serial()) {
87 if (combat_walking_ != CD_COMBAT_W) {
88 molog("[battle]: Moving west\n");
89- opponent.send_signal(game, "wakeup");
90+ opponent->send_signal(game, "wakeup");
91 return start_task_move_in_battle(game, CD_WALK_W);
92 }
93 } else {
94 if (combat_walking_ != CD_COMBAT_E) {
95 molog("[battle]: Moving east\n");
96- opponent.send_signal(game, "wakeup");
97+ opponent->send_signal(game, "wakeup");
98 return start_task_move_in_battle(game, CD_WALK_E);
99 }
100 }

Subscribers

People subscribed via source and target branches

to all changes: