From 0dd59211aa2c59eb3053c0030947b9b42716bdf4 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 18 May 2012 16:29:19 +0200 Subject: [PATCH] Fix march not to wipe out concurrent updates March code reads the land units into a land unit list, and writes them back when it changes them, e.g. when a land unit stops. If a land unit changes in the land unit file while it is in such a land unit list, the copy in the land unit list becomes stale, and must not be used. To that end, do_unit_move() calls lnd_mar() after prompting for path or destination. lnd_mar() re-reads all the land units. Unfortunately, it still writes back stale copies in certain circumstances. Known ways to trigger such writes: * Deity loads land unit onto a ship or land unit * Land unit's crew killed just right, e.g. by collateral damage from interdiction, followed by additional updates, such as shell fire damage * Sector no longer owned or allied, e.g. allied sector captured by an enemy (own sector would kill or retreat the land unit) Writing a stale copy wipes out the updates that made the copy stale, and triggers a seqno mismatch oops. For instance, damage that follows killing of all crew by collateral damage from interdiction is wiped out. If no damage follows, we still get a generation oops. --- src/lib/subs/lndsub.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/lib/subs/lndsub.c b/src/lib/subs/lndsub.c index 9a414b90b..5bc2c329a 100644 --- a/src/lib/subs/lndsub.c +++ b/src/lib/subs/lndsub.c @@ -460,8 +460,8 @@ lnd_mar(struct emp_qelem *list, double *minmobp, double *maxmobp, struct emp_qelem *qp; struct emp_qelem *next; struct ulist *llp; + struct lndstr *lp; struct sctstr sect; - struct lndstr land; coord allx; coord ally; int first = 1; @@ -473,54 +473,54 @@ lnd_mar(struct emp_qelem *list, double *minmobp, double *maxmobp, for (qp = list->q_back; qp != list; qp = next) { next = qp->q_back; llp = (struct ulist *)qp; - getland(llp->unit.land.lnd_uid, &land); - if (land.lnd_own != actor) { + lp = &llp->unit.land; + getland(lp->lnd_uid, lp); + if (lp->lnd_own != actor) { mpr(actor, "%s was disbanded at %s\n", - prland(&land), xyas(land.lnd_x, land.lnd_y, actor)); + prland(lp), xyas(lp->lnd_x, lp->lnd_y, actor)); emp_remque((struct emp_qelem *)llp); free(llp); continue; } - if (land.lnd_ship >= 0) { + if (lp->lnd_ship >= 0) { lnd_stays(actor, "is on a ship", llp); continue; } - if (land.lnd_land >= 0) { + if (lp->lnd_land >= 0) { lnd_stays(actor, "is on a unit", llp); continue; } - if (!getsect(land.lnd_x, land.lnd_y, §)) { + if (!getsect(lp->lnd_x, lp->lnd_y, §)) { lnd_stays(actor, "was sucked into the sky by a strange looking spaceland", llp); /* heh -KHS */ continue; } - if (!(lchr[(int)llp->unit.land.lnd_type].l_flags & L_SPY) && - !(lchr[(int)llp->unit.land.lnd_type].l_flags & L_TRAIN) && - llp->unit.land.lnd_item[I_MILIT] == 0) { + if (!(lchr[lp->lnd_type].l_flags & L_SPY) && + !(lchr[lp->lnd_type].l_flags & L_TRAIN) && + lp->lnd_item[I_MILIT] == 0) { lnd_stays(actor, "has no mil on it to guide it", llp); continue; } if (relations_with(sect.sct_own, actor) != ALLIED && - !(lchr[(int)llp->unit.land.lnd_type].l_flags & L_SPY) && + !(lchr[lp->lnd_type].l_flags & L_SPY) && sect.sct_own) { sprintf(mess, "has been kidnapped by %s", cname(sect.sct_own)); lnd_stays(actor, mess, llp); continue; } if (first) { - allx = land.lnd_x; - ally = land.lnd_y; + allx = lp->lnd_x; + ally = lp->lnd_y; first = 0; } - if (land.lnd_x != allx || land.lnd_y != ally) + if (lp->lnd_x != allx || lp->lnd_y != ally) *togetherp = 0; - if (land.lnd_mobil + 1 < (int)llp->mobil) { - llp->mobil = land.lnd_mobil; + if (lp->lnd_mobil + 1 < (int)llp->mobil) { + llp->mobil = lp->lnd_mobil; } if (llp->mobil < *minmobp) *minmobp = llp->mobil; if (llp->mobil > *maxmobp) *maxmobp = llp->mobil; - llp->unit.land = land; } } -- 2.43.0