Ticket #78170

Attack from transport crash

Eröffnet am: 2024-05-10 14:44 Letztes Update: 2024-06-02 07:54

Auswertung:
Verantwortlicher:
Typ:
Status:
Geschlossen
Komponente:
Meilenstein:
Priorität:
5 - Mittel
Schweregrad:
5 - Mittel
Lösung:
Gefixt
Datei:
3

Details

Similar to bug #62981, but this time with default ruleset (S3_1). Tested with client gtk3.22 and qt6.

If I load the attached savegame, I use the mouse to select one of the Musketers (all in sentry state) inside the Transport, and I use "drag and drop" (mouse gesture) to attack the adjacent enemy Mech Inf, then the Musketer is deselected, loses the sentry state, and it changes to a "waiting orders" state with a "?" icon. If I select the same Musketer again, and I click attack when the popup appear, the game crashes with a segmentation fault error:

in utype_can_do_action() [unittype.c::449]: assertion '(signed int)(utype_index(putype)) >= 0 && (signed int)(utype_index(putype)) < (signed int) sizeof((unit_can_act_cacheact_id).vec) * 8' failed.

I'm playing a game where this kind of crashes are common (any action performed from a transport with a sentry unit), but it uses to work if I just reload the game. This savegame crashes to me every time I try the same attack.

Ticket-Verlauf (3/20 Historien)

2024-05-10 14:44 Aktualisiert von: bard
  • New Ticket "Attack from transport crash" created
2024-05-10 14:46 Aktualisiert von: bard
  • File 3_1_0-civ2civ3_default-attackcrash.sav.xz (File ID: 13752) is attached
2024-05-10 14:47 Aktualisiert von: bard
  • File 3_1_0-civ2civ3_default-attackcrash.sav.xz (File ID: 13753) is attached
2024-05-10 14:48 Aktualisiert von: bard
  • File 3_1_0-civ2civ3_default-attackcrash.sav.xz (File ID: 13752) is deleted
2024-05-10 14:49 Aktualisiert von: bard
  • File 3_1_0-civ2civ3_default-attackcrash.sav.xz (File ID: 13753) is deleted
2024-05-10 20:54 Aktualisiert von: cazfi
Kommentar

I can't reproduce (with the head of S3_1), nor does valgrind reveal anything like accessing the Musketeer memory after it has died. Seems that the only way forward would be that you provide full backtrace of the crash yourself. https://www.freeciv.org/wiki/Bug_Reporting

2024-05-11 16:27 Aktualisiert von: bard
Kommentar

Reply To cazfi

I can't reproduce (with the head of S3_1), nor does valgrind reveal anything like accessing the Musketeer memory after it has died. Seems that the only way forward would be that you provide full backtrace of the crash yourself. https://www.freeciv.org/wiki/Bug_Reporting

The head of S3_1 (v3.1.1+ from today) still crashes to me. Gdb backtrace:

#0  tile_to_canvas_pos (canvas_x=canvas_x@entry=0x7fffffffcda8, canvas_y=canvas_y@entry=0x7fffffffcdac, zoom=<optimized out>, ptile=ptile@entry=0xed407f99fe4eb523)
    at mapview_common.c:708
        center_map_x = 14
        center_map_y = 24
        dx = 17
        dy = 0
        tile_x = <optimized out>
        tile_y = <optimized out>
        __FUNCTION__ = "tile_to_canvas_pos"
#1  0x00005555555f1fde in tile_visible_and_not_on_border_mapcanvas (ptile=0xed407f99fe4eb523) at mapview_common.c:1281
        canvas_x = 0
        canvas_y = 0
        xmin = -2276
        ymin = 531
        xmax = 2228
        ymax = 2325
        xsize = 1096
        ysize = 667
        scroll_x = -980
        scroll_y = 602
        border_x = 48
        border_y = 24
        same = false
#2  0x00005555555d0c18 in unit_focus_advance () at control.c:725
        focus_tile = 0x0
        candidate = 0x55555cb08050
        num_units_in_old_focus = 0
        __FUNCTION__ = "unit_focus_advance"
#3  0x00005555555cb10a in client_remove_unit (punit=0x0, punit@entry=0x55555cb08050) at climisc.c:100
        pcity = <optimized out>
        ptile = 0x55555bfa0240
        hc = 0

                        old_unit = {utype = 0x555556273e30 <unit_types+24048>, tile = 0x55555bfa0240, refcount = 1, facing = DIR8_NORTHWEST, owner = 0x555556c162f0, nationality = 0x555556c162f0, id = 126, homecity = 0, upkeep = {1, 0, 0, 1, 0, 0}, moves_left = 6, hp = 20, veteran = 0, fuel = 0, goto_tile = 0x0, activity = ACTIVITY_IDLE, activity_count = 0, activity_target = 0x0, changed_from = ACTIVITY_IDLE, changed_from_count = 0, changed_from_target = 0x0, ssa_controller = SSA_NONE, moved = false, paradropped = false, done_moving = false, transporter = 0x0, transporting = 0x555559f60f70, carrying = 0x0, battlegroup = -1, has_orders = false, orders = {length = 0, index = 0, repeat = false, vigilant = false, list = 0x0}, action_decision_want = ACT_DEC_ACTIVE, action_decision_tile = 0x55555bf9e2c0, stay = false, {client = {focus_status = FOCUS--Type <RET> for more, q to quit, c to continue without paging--
_AVAIL, transported_by = -1, occupied = false, colored = false, color_index = 0, asking_city_name = false, act_prob_cache = 0x0}, server = {debug = false, adv = 0x0, ais = {0x0, 0x0}, birth_turn = 0, ord_map = 0, ord_city = 0, vision = 0x0, action_timestamp = 0, action_turn = 0, moving = 0x0, dying = false, removal_callback = 0x0, upkeep_paid = {0, 0, 0, 0, 0, 0}}}}
        old = 1
        update = true
        __FUNCTION__ = "client_remove_unit"
#4  0x00005555555fe052 in handle_unit_remove (unit_id16=<optimized out>, unit_id32=<optimized out>) at packhand.c:560
        punit = 0x55555cb08050
        cargos = <optimized out>
        powner = 0x555556c162f0
        need_economy_report_update = true
        __FUNCTION__ = "handle_unit_remove"
#5  0x000055555560c2a1 in client_handle_packet (type=type@entry=PACKET_UNIT_REMOVE, packet=packet@entry=0x555557f4ccf0) at packhand_gen.c:207
#6  0x00005555555c719a in client_packet_input (packet=packet@entry=0x555557f4ccf0, type=62) at client_main.c:792
        __FUNCTION__ = "client_packet_input"
#7  0x00005555555ceec4 in input_from_server (fd=<optimized out>) at clinet.c:420
        type = PACKET_UNIT_REMOVE
        packet = 0x555557f4ccf0
        nb = <optimized out>
        __FUNCTION__ = "input_from_server"
#8  0x00005555555c2494 in get_net_input (source=<optimized out>, condition=<optimized out>, data=<optimized out>) at gui_main.c:2222
#9  0x00007ffff6c6ac44 in g_main_context_dispatch () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#10 0x00007ffff6cc0258 in  () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#11 0x00007ffff6c6a2b3 in g_main_loop_run () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#12 0x00007ffff74aacfd in gtk_main () at /lib/x86_64-linux-gnu/libgtk-3.so.0
#13 0x00005555555c50b2 in ui_main (argc=<optimized out>, argc@entry=1, argv=<optimized out>, argv@entry=0x7fffffffd9f8) at gui_main.c:1987
        window_name = "Freeciv (gtk3.22)\000\000\000\000\000\000\000\000/\035k/\\rW\340\324\377\377\377\177\000\000\030\000\000\000\000\000\000\000\250t\206UUU\000\000曃UUU\000\000\000\000\000\000\000\000\000\000\030", '\000' <repetidos 23 veces>, "\340\353\210UUU\000\000Z\235\203UUU\000\000\001\000\000\000\000\000\000\000'l\201UUU", '\000' <repetidos 26 veces>, " \000\000\000\060\000\000\000\320\324\377\377\001\000\000\000\360\323\377\377\377\177\000\000colors.p\000/\035k/\\rW_backgro\200\377\377\377\377\377\377\377"...
        toplevel_font_name = <optimized out>
        sig = <optimized out>
        __FUNCTION__ = "ui_main"
#14 0x00005555555c8455 in client_main (argc=1, argv=0x7fffffffd9f8, postpone_tileset=<optimized out>) at client_main.c:703
        i = 1
        loglevel = LOG_NORMAL
        ui_options = <optimized out>
        ui_separator = <optimized out>
--Type <RET> for more, q to quit, c to continue without paging--
        option = <optimized out>
        fatal_assertions = -1
        aii = 2
        uret = <optimized out>
        __FUNCTION__ = "client_main"
#15 0x00007ffff6a15d90 in __libc_start_call_main (main=main@entry=0x5555555c1a10 <main>, argc=argc@entry=1, argv=argv@entry=0x7fffffffd9f8)
    at ../sysdeps/nptl/libc_start_call_main.h:58
        self = <optimized out>
        result = <optimized out>

                      unwind_buf = {cancel_jmp_buf = {{jmp_buf = {0, 913343395805536372, 140737488345592, 93824992680464, 93824996397528, 140737354125376, -913343396845576076, -913327234994265996}, mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x0, 0x0}, data = {prev = 0x0, cleanup = 0x0, canceltype = 0}}}
        not_first_call = <optimized out>
#16 0x00007ffff6a15e40 in __libc_start_main_impl
     (main=0x5555555c1a10 <main>, argc=1, argv=0x7fffffffd9f8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffd9e8)
    at ../csu/libc-start.c:392
#17 0x00005555555c1a45 in _start ()

2024-05-11 16:31 Aktualisiert von: bard
Kommentar

This is gdb bt with qt6 client (this time S3_1 from 20 days ago):

#0  0x0000555555947141 in utype_can_do_action (putype=<optimized out>, act_id=<optimized out>) at unittype.c:449
        __FUNCTION__ = "utype_can_do_action"
#1  0x0000555555948f4e in utype_can_do_action_result (putype=0x55555c50a140, result=result@entry=ACTRES_FOUND_CITY) at unittype.c:465
        paction_iter = 0x0
        paction = <optimized out>
        __FUNCTION__ = "utype_can_do_action_result"
#2  0x000055555594d19a in utype_is_cityfounder (utype=<optimized out>) at unittype.c:2974
No locales.
#3  0x0000555555944479 in unit_is_cityfounder (punit=punit@entry=0x55555c4b46f0) at unit.c:2621
No locales.
#4  0x000055555569eef0 in unit_drawn_with_city_outline (punit=punit@entry=0x55555c4b46f0, check_focus=check_focus@entry=true) at tilespec.c:5277
No locales.
#5  0x0000555555673b66 in refresh_unit_mapcanvas (punit=punit@entry=0x55555c4b46f0, ptile=0x7ffff640ee80 <main_arena+512>, full_refresh=full_refresh@entry=true, 
    write_to_screen=write_to_screen@entry=false) at mapview_common.c:515
No locales.
#6  0x000055555564abe0 in current_focus_append (punit=0x55555c4b46f0) at control.c:448
No locales.
#7  0x000055555564ad82 in unit_focus_set (punit=punit@entry=0x55555c4b46f0) at control.c:544
        focus_changed = true
        __FUNCTION__ = "unit_focus_set"
#8  0x000055555564b260 in unit_focus_set (punit=0x55555c4b46f0) at control.c:506
        focus_changed = false
        focus_changed = <optimized out>
        __FUNCTION__ = "unit_focus_set"
        punit_old_iter = <optimized out>
        punit_old = <optimized out>
        punit_old_iter = <optimized out>
        punit_old = <optimized out>
#9  unit_focus_advance () at control.c:750
        candidate = 0x55555c4b46f0
        num_units_in_old_focus = 0
        __FUNCTION__ = "unit_focus_advance"
#10 0x00005555556457aa in client_remove_unit (punit=0x0, punit@entry=0x55555c4b46f0) at climisc.c:100
        pcity = <optimized out>
        ptile = 0x55555c457200
        hc = 0
        old_unit = {utype = 0x5555563c9a30 <unit_types+24048>, tile = 0x55555c457200, refcount = 1, facing = DIR8_NORTHWEST, owner = 0x55555ad34840, 
          nationality = 0x55555ad34840, id = 126, homecity = 0, upkeep = {1, 0, 0, 1, 0, 0}, moves_left = 6, hp = 0, veteran = 0, fuel = 0, goto_tile = 0x0, 
--Type <RET> for more, q to quit, c to continue without paging--
          activity = ACTIVITY_IDLE, activity_count = 0, activity_target = 0x0, changed_from = ACTIVITY_IDLE, changed_from_count = 0, changed_from_target = 0x0, 
          ssa_controller = SSA_NONE, moved = false, paradropped = false, done_moving = false, transporter = 0x0, transporting = 0x55555c4b4850, carrying = 0x0, 
          battlegroup = -1, has_orders = false, orders = {length = 0, index = 0, repeat = false, vigilant = false, list = 0x0}, 
          action_decision_want = ACT_DEC_ACTIVE, action_decision_tile = 0x55555c455280, stay = false, {client = {focus_status = FOCUS_AVAIL, transported_by = -1, 
              occupied = false, colored = false, color_index = 0, asking_city_name = false, act_prob_cache = 0x0}, server = {debug = false, adv = 0x0, ais = {0x0, 
                0x0}, birth_turn = 0, ord_map = 0, ord_city = 0, vision = 0x0, action_timestamp = 0, action_turn = 0, moving = 0x0, dying = false, 
              removal_callback = 0x0, upkeep_paid = {0, 0, 0, 0, 0, 0}}}}
        old = 1
        update = true
        __FUNCTION__ = "client_remove_unit"
#11 0x00005555556786e2 in handle_unit_remove (unit_id16=<optimized out>, unit_id32=<optimized out>) at packhand.c:560
        punit = 0x55555c4b46f0
        cargos = <optimized out>
        powner = 0x55555ad34840
        need_economy_report_update = true
        __FUNCTION__ = "handle_unit_remove"
#12 0x0000555555686931 in client_handle_packet (type=type@entry=PACKET_UNIT_REMOVE, packet=packet@entry=0x55555c508d20) at packhand_gen.c:207
No locales.
#13 0x000055555564183a in client_packet_input (packet=packet@entry=0x55555c508d20, type=62) at client_main.c:792
        __FUNCTION__ = "client_packet_input"
#14 0x0000555555649564 in input_from_server (fd=<optimized out>) at clinet.c:420
        type = PACKET_UNIT_REMOVE
        packet = 0x55555c508d20
        nb = <optimized out>
        __FUNCTION__ = "input_from_server"
#15 0x0000555555700a64 in fc_client::server_input (this=0x5555572827a0, sock=19) at fc_client.cpp:505
No locales.
#16 0x00007ffff7064023 in ?? () from /lib/x86_64-linux-gnu/libQt6Core.so.6
No symbol table info available.
#17 0x00007ffff7070baa in QSocketNotifier::activated(QSocketDescriptor, QSocketNotifier::Type, QSocketNotifier::QPrivateSignal) ()
   from /lib/x86_64-linux-gnu/libQt6Core.so.6
No symbol table info available.
#18 0x00007ffff7071199 in QSocketNotifier::event(QEvent*) () from /lib/x86_64-linux-gnu/libQt6Core.so.6
No symbol table info available.
#19 0x00007ffff68d1d36 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /lib/x86_64-linux-gnu/libQt6Widgets.so.6
No symbol table info available.
#20 0x00007ffff700ba58 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () from /lib/x86_64-linux-gnu/libQt6Core.so.6
No symbol table info available.
--Type <RET> for more, q to quit, c to continue without paging--
#21 0x00007ffff7234bd7 in ?? () from /lib/x86_64-linux-gnu/libQt6Core.so.6
No symbol table info available.
#22 0x00007ffff3b7bd3b in g_main_context_dispatch () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
No symbol table info available.
#23 0x00007ffff3bd1258 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
No symbol table info available.
#24 0x00007ffff3b793e3 in g_main_context_iteration () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
No symbol table info available.
#25 0x00007ffff7233eae in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /lib/x86_64-linux-gnu/libQt6Core.so.6
No symbol table info available.
#26 0x00007ffff7018adb in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /lib/x86_64-linux-gnu/libQt6Core.so.6
No symbol table info available.
#27 0x00007ffff70140f3 in QCoreApplication::exec() () from /lib/x86_64-linux-gnu/libQt6Core.so.6
No symbol table info available.
#28 0x0000555555701c4c in fc_client::fc_main (this=0x5555572827a0, qapp=0x55555651be00) at fc_client.cpp:273
No locales.
#29 0x000055555563f7b3 in qtg_ui_main (argc=<optimized out>, argv=0x7fffffffda08) at gui_main.cpp:211
        qpm = <optimized out>
        app_icon = {d = 0x5555568a69b0}
        tsret = 0
#30 0x0000555555642af5 in client_main (argc=1, argv=0x7fffffffda08, postpone_tileset=<optimized out>) at client_main.c:703
        i = 1
        loglevel = LOG_NORMAL
        ui_options = <optimized out>
        ui_separator = <optimized out>
        option = <optimized out>
        fatal_assertions = -1
        aii = 2
        uret = <optimized out>
        __FUNCTION__ = "client_main"
#31 0x00007ffff621dd90 in __libc_start_call_main (main=main@entry=0x55555563d1c0 <main(int, char**)>, argc=argc@entry=1, argv=argv@entry=0x7fffffffda08)
    at ../sysdeps/nptl/libc_start_call_main.h:58
        self = <optimized out>
        result = <optimized out>
        unwind_buf = {cancel_jmp_buf = {{jmp_buf = {0, 5550509266952179337, 140737488345608, 93824993186240, 93824997735288, 140737354125376, -5550509267952284023, 
                -5550490249962402167}, mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x0, 0x0}, data = {prev = 0x0, cleanup = 0x0, canceltype = 0}}}
        not_first_call = <optimized out>
#32 0x00007ffff621de40 in __libc_start_main_impl (main=0x55555563d1c0 <main(int, char**)>, argc=1, argv=0x7fffffffda08, init=<optimized out>, fini=<optimized out>, 
--Type <RET> for more, q to quit, c to continue without paging--
    rtld_fini=<optimized out>, stack_end=0x7fffffffd9f8) at ../csu/libc-start.c:392
No locales.
#33 0x000055555563ee55 in _start ()

2024-05-12 01:21 Aktualisiert von: cazfi
  • Komponente Update from (Keine) to Client common
Kommentar

So the problem seems to be in unit focus handling. Didn't figure out this particular issue yet, but while looking for it, found https://redmine.freeciv.org/issues/586

2024-05-12 13:34 Aktualisiert von: cazfi
Kommentar

I see the problem now, from the Qt-client backtrace. client_remove_unit() has destroyed the unit, but has not yet removed it from the list of units on the tile. unit_focus_advance() notices the unit from the tile as a "new" (since it's already been removed from current focus) focus unit, and starts using it. My fix to https://redmine.freeciv.org/issues/586 makes it less likely that all this happens, but I'm not sure it covers all cases (this is not the bug it's meant to fix, anyway)

2024-05-12 15:15 Aktualisiert von: cazfi
Kommentar

While osdn has refused to send my comments about the first patch, the second one has already been made. Now you likely want to test unit_focus_advanceIterateSafe.patch first, to see if it resolves the issue for you. Seems to me that the old code could have messed memory with undefined results.

If it doesn't help:
Can you try to reproduce the issue with attached DeathFromTransportDebug.patch applied, and paste the logs between BEGINS and ENDS.

For reference, here's what I got on S3_1 HEAD, and where I see no problems (the removed unit (pointer) is not getting back to focus, like seems to happen in your backtrace):

3: BEGINS
3: client_remove_unit() 0x556fcdfba580 at (14, 24)
3: client_remove_unit(): 1 units in focus.
3: End of control_unit_killed(): 0 units in focus.
3: unit_focus_advance(): urgent focus size 0
3: Center tile: (14, 24)
3: best focus candidate: 0x556fcc10bd40
3: ENDS
2024-05-12 19:16 Aktualisiert von: bard
Kommentar

I'm glad you found the cause, I'll test the patch.

2024-05-12 20:05 Aktualisiert von: None
Kommentar

I confirm the patch (unit_focus_advanceIterateSafe.patch) fixes the crash I reported in this ticket, and also the crash from #62981 (healer killed by script). Thank you.

However, even if there are no crashes, I still find problematic the way the unit focus jumps to the next unit before you have finished the movement/actions. For example: * When I use goto to move a unit, when it arrives to the desired tile, the focus jumps to the next unit even when the current one still has remaining move points. * When I order to disembark, the unit is deselected before asking the desired action * And similar issues when I order diplomats or caravans to perform actions. They are deselected, the focus jumps to next unit, and I have to select them again to finish the action.

Since you could not reproduce the crash, I'm thinking it could be dependant on client settings, I'll test to change them, because it didn't happen in 3.0 to me.

2024-05-12 20:07 Aktualisiert von: bard
Kommentar

I confirm the patch (unit_focus_advanceIterateSafe.patch) fixes the crash I reported in this ticket, and also the crash from #62981 (healer killed by script). Thank you.

However, even if there are no crashes, I still find problematic the way the unit focus jumps to the next unit before you have finished the movement/actions. For example:

  • When I use goto to move a unit, when it arrives to the desired tile, the focus jumps to the next unit even when the current one still has remaining move points.
  • When I order to disembark, the unit is deselected before asking the desired action
  • And similar issues when I order diplomats or caravans to perform actions. They are deselected, the focus jumps to next unit, and I have to select them again to finish the action.

Since you could not reproduce the crash, I'm thinking it could be dependant on client settings, I'll test to change them, because it didn't happen in 3.0 to me.

2024-05-13 01:01 Aktualisiert von: cazfi
  • Verantwortlicher Update from (Keine) to cazfi
  • Lösung Update from Keine to Accepted
Kommentar

I'll plan to apply the fix also to S2_6. It applies cleanly.

While I couldn't reproduce the crash, I am seeing various odd behaviors with the focus advancement in general.

2024-06-02 07:15 Aktualisiert von: cazfi
Kommentar

Reply To cazfi

While I couldn't reproduce the crash, I am seeing various odd behaviors with the focus advancement in general.

-> https://redmine.freeciv.org/issues/694

2024-06-02 07:54 Aktualisiert von: cazfi
  • Status Update from Offen to Geschlossen
  • Lösung Update from Accepted to Gefixt

Bearbeiten

Please login to add comment to this ticket » Anmelden