Eintragsdetails ansehen

IDProjektKategorieSichtbarkeitZuletzt aktualisiert
0002123EresseaZAUBERöffentlich2015-08-16 20:02
ReporterEnnoBearbeitung durchEnno 
PrioritätdringendAuswirkungAbsturzReproduzierbarnicht getestet
Status geschlossenLösungerledigt 
Produktversion3.5 
Zielversion3.5Behoben in Version3.5 
Zusammenfassung0002123: crash in update_gbdream
Beschreibung

See callstack below. When calling update_gbdream while reading the save file, c->magician may not be set (it gets delayed in curse_read by read_reference), and update_gbdream bombs because mage is a null-pointer.

This is currently blocking the next turn, because it fails to read the 939.dat file for E2.

Schritte zur Reproduktion

call stack:

#0 0x00000000004c143c in alliedunit (u=0x0, f2=0x1c26730, mode=16)
at /home/eressea/eressea/git/src/kernel/config.c:533
#1 0x00000000004e165d in update_gbdream (u=0x21fa3d0, bonus=0, c=0x21f7960,
gbdream_ct=0x73d960, sign=1)
at /home/eressea/eressea/git/src/kernel/unit.c:1284
0000002 0x00000000004e184a in att_modification (u=0x21fa3d0, sk=SK_MAGIC)
at /home/eressea/eressea/git/src/kernel/unit.c:1330
#3 0x00000000004e1958 in get_modifier (u=0x21fa3d0, sk=SK_MAGIC, level=15,
r=0x21f76a0, noitem=false)
at /home/eressea/eressea/git/src/kernel/unit.c:1355
0000004 0x00000000004e1a71 in eff_skill (u=0x21fa3d0, sk=SK_MAGIC, r=0x21f76a0)
at /home/eressea/eressea/git/src/kernel/unit.c:1382
#5 0x00000000004e2caf in effskill (u=0x21fa3d0, sk=SK_MAGIC)
at /home/eressea/eressea/git/src/kernel/unit.c:1856
#6 0x00000000004daadb in readgame (filename=0x1c99b28 "939.dat", backup=0)
at /home/eressea/eressea/git/src/kernel/save.c:1621
#7 0x0000000000421891 in eressea_read_game (filename=0x1c99b28 "939.dat")
at /home/eressea/eressea/git/src/bind_eressea.c:22
0000008 0x000000000041e619 in tolua_eressea_eressea_read_game00 (tolua_S=0x1be06c0)
at /home/eressea/eressea/git/src/eressea.pkg.c:70

Zusätzliche Informationen

TODO:

  • add an assert in update_gbdreams
  • figure out how to avoid calling this during readgame
Partei0
SpielE2
Report939

Notizen / Dateien

Enno

Enno

2015-08-02 20:59

Administrator   ~0005995

Ich verstehe das nicht. Dort ist schon auf mage == null getestet, und die lazy Evaluation von C sollte dafür sorgen, dass der hintere Teil des ODER nicht ausgewertet wird, er alliedunit() also nicht aufrufen muss.

        if (mage == NULL || mage->number == 0
            || (sign>0?alliedunit(mage, u->faction, HELP_GUARD):!alliedunit(mage, u->faction, HELP_GUARD))) {
Enno

Enno

2015-08-02 21:15

Administrator   ~0005996

regardless of that, update_gbdream makes no sense when it doesn't know the magician, because it needs to call alliedunit() to determine whether the curse is effective. So it's wrong to call it before all the resolve_unit() calls have been made. An assert(c->magician) is the right thing to do here, and then fix the logical error upstream. Which is here:

#7 0x00000000004dab1b in readgame (filename=0x1d3e7f8 "939.dat", backup=0)
at /home/eressea/eressea/git/src/kernel/save.c:1621
1621 int skl = effskill(u, SK_MAGIC);

Enno

Enno

2015-08-02 22:01

Administrator   ~0005997

Das übergeordnete Problem ist, dass faction::max_spelllevel während readgame berechnet wird, und aktualisiert wann immer in Magier eingelesen wurde. Wenn der Magier dabei in einer Region mit gute/schlechte Träume steht, kann sein Talent nicht bestimmt werden, das darf also nicht passieren, ehe resolve() aufgerufen wurde (passiert erst später in readgame). Einfacher Fix ist, max_spelllevel in einem zusätzlichen Pass am Ende von readgame zu berechnen, aber das ist O(Alle Einheiten) komplex. Besser wäre es, das on-demand zu berechnen wenn es gebraucht wird, in einer Getter-Funktion (die es aber noch nicht gibt), und alle Magier der Partei zu durchsuchen, was dann nur O(#f.units) ist.

Enno

Enno

2015-08-02 22:07

Administrator   ~0005998

Hmm. Selbst wenn ich das mache (ich habe erst einmal die schnelle Lösung implementiert), ist immer noch ein curse mit c->magician==null in den Daten. Der hat die ID 652303, mal gucken, warum der nicht resolved wurde...

Enno

Enno

2015-08-02 22:11

Administrator   ~0005999

Der curse ist gar nicht "gbdreams", sondern "holyground", und hat keinen Magier (ist wahrscheinlich tot, aber holyground hält ja ewig). Warum triggert der meine Assertion?

Enno

Enno

2015-08-02 22:12

Administrator   ~0006000

Oh, I see. Der Test auf c->type == gbdream_ct passiert erst in update_gbdream, aber mein Check war vorher. Das ist ja alles verkehrte Welt, der Test sollte vor dem Aufruf schon passieren.

Enno

Enno

2015-08-02 23:17

Administrator   ~0006001

all done, this hotfix will be in version 3.5.4

Enno

Enno

2015-08-02 23:23

Administrator   ~0006002

new server version 3.5.4 is installed

Eintrags-Historie

Änderungsdatum Benutzername Feld Änderung
2015-08-02 11:01 Enno Neuer Eintrag
2015-08-02 11:01 Enno Status neu => zugewiesen
2015-08-02 11:01 Enno Bearbeitung durch => Enno
2015-08-02 20:59 Enno Notiz hinzugefügt: 0005995
2015-08-02 21:15 Enno Notiz hinzugefügt: 0005996
2015-08-02 22:01 Enno Notiz hinzugefügt: 0005997
2015-08-02 22:07 Enno Notiz hinzugefügt: 0005998
2015-08-02 22:11 Enno Notiz hinzugefügt: 0005999
2015-08-02 22:12 Enno Notiz hinzugefügt: 0006000
2015-08-02 23:17 Enno Notiz hinzugefügt: 0006001
2015-08-02 23:23 Enno Notiz hinzugefügt: 0006002
2015-08-02 23:23 Enno Status zugewiesen => erledigt
2015-08-02 23:23 Enno Behoben in Version => 3.5
2015-08-02 23:23 Enno Lösung offen => erledigt
2015-08-16 20:02 Enno Status erledigt => geschlossen