joncampbell123 / dosbox-x

DOSBox-X fork of the DOSBox project
GNU General Public License v2.0
2.75k stars 381 forks source link

Crash - Days of Thunder #3916

Closed mart0258 closed 1 year ago

mart0258 commented 1 year ago

Describe the bug

The game Days of Thunder is causing Dosbox-X to freeze after it exits. There is a few seconds of delay before DosBox-X freezes, where it no longer accepts any input (including the menu or even resizing the window).

Mainline versions of Dosbox aren't affected. The freeze isn't specific to one computer.

Steps to reproduce the behaviour

  1. Launch "DOT.exe". (Older versions of DosBox-X mention Loadfix, although that could be auto-configuration.)
  2. Press ESC to reach main menu.
  3. Choose Quit to Dos.

Expected behavior

Avoiding the crash.

What operating system(s) this bug have occurred on?

Windows 10

What version(s) of DOSBox-X have this bug?

v2022.12.26, MinGW SDL1, 64-bit

Used configuration

No response

Output log

No response

Additional information

Additional versions tested, all having the freeze:

Have you checked that no similar bug report(s) exist?

Code of Conduct & Contributing Guidelines

grapeli commented 1 year ago

I confirm this behavior. DOSBox-X after a short while falls into a loop with no way out. The only thing left is to kill the dosbox-x process. This can only be circumvented by immediately issuing the exit command after completing Days of Thunder (1990). dosbox-x -exit dot.exe

Backtrace log from gdb.

GNU gdb (GDB) 12.1
Reading symbols from ./dosbox-x...
(gdb) run
Thread 1 "dosbox-x" received signal SIGQUIT, Quit.
0x0000555558c3e7f4 in Allocate () at /b/s/w/ir/cache/builder/src/third_party/llvm/compiler-rt/lib/asan/asan_fake_stack.cpp:91
91  /b/s/w/ir/cache/builder/src/third_party/llvm/compiler-rt/lib/asan/asan_fake_stack.cpp: No such file or directory.
(gdb) bt full
#0  0x0000555558c3e7f4 in Allocate () at /b/s/w/ir/cache/builder/src/third_party/llvm/compiler-rt/lib/asan/asan_fake_stack.cpp:91
No locals.
#1  OnMalloc () at /b/s/w/ir/cache/builder/src/third_party/llvm/compiler-rt/lib/asan/asan_fake_stack.cpp:211
No locals.
#2  __asan_stack_malloc_0 () at /b/s/w/ir/cache/builder/src/third_party/llvm/compiler-rt/lib/asan/asan_fake_stack.cpp:255
No locals.
#3  0x000055555ba6a216 in PIT_Block::track_time (this=0x55555f52af80 <pit>, t=9738.54900000000000038) at timer.cpp:113
No locals.
#4  0x000055555ba55fee in PIT0_Event () at timer.cpp:314
        err = 1098.49126118228394866
#5  0x000055555b9ceccb in PIC_RunQueue () at pic.cpp:745
        entry = 0x55556257d7f0 <pic_queue+8880>
        index_nd = 1647
#6  0x0000555558d07c9a in Normal_Loop () at dosbox.cpp:352
        saved_allow = false
        ret = 0
        pf = @0x10007ea11390: {<std::exception> = {_vptr.exception = 0xf5f5f5f5f5f5f5f5}, lin_addr = 4126537205, page_addr = 17723342345328784885, 
          faultcode = 17723342345328784885}
        gpf = @0x7ffff50c9c80: {<std::exception> = {_vptr.exception = 0x45e0360e}, <No data fields>}
        x = 32767
#7  0x0000555558d089af in DOSBOX_RunMachine () at dosbox.cpp:632
        ret = 0
        p_last_callback = 31
#8  0x000055555c125cf6 in CALLBACK_RunRealInt (intnum=22 '\026') at callback.cpp:209
        oldeip = 54016
        oldcs = 61440
#9  0x000055555920138a in device_CON::Read (this=0x60b000075730, data=0x7ffff5446040 "x", size=0x7ffff5021660) at ./dev_con.h:733
        oldax = 19200
        count = 0
        defattr = 7 '\a'
#10 0x000055555921f663 in DOS_Device::Read (this=0x6060000fd040, data=0x7ffff5446040 "x", size=0x7ffff5021660) at dos_devices.cpp:625
No locals.
#11 0x00005555592742b8 in DOS_ReadFile (entry=0, data=0x7ffff5446040 "x", amount=0x7ffff5446050, fcb=false) at dos_files.cpp:657
        handle = 1
        toread = 1
        ret = true
#12 0x0000555559e1330a in DOS_Shell::InputCommand (this=0x6110000bd780, line=0x7ffff5682020 "ex") at shell_misc.cpp:486
        size = 4092
        c = 120 'x'
        n = 1
        str_len = 2
        str_index = 2
        len = 0
        current_hist = false
        cr = 120
        it_history = <error reading variable: Cannot create a lazy string with address 0x0, and a non-zero length.>
Python Exception <class 'OverflowError'>: int too big to convert
        it_completion = 
#13 0x0000555559d08d6a in DOS_Shell::Run (this=0x6110000bd780) at shell.cpp:1057
        input_line = "ex\000t /a\000/tmp/dos/DaysofTh\000 P330 T6", '\000' <repeats 4061 times>
        line = ""
        optP = false
        optC = false
        optK = false
        optInit = true
#14 0x0000555559d145f7 in SHELL_Run () at shell.cpp:1948
        section = 0x60c000006d00
        altshell = false
        namestr = '\000' <repeats 511 times>
        tmpstr = '\000' <repeats 511 times>
        name = 0x7ffff55f0090 ""
        tmp = 0x7ffff55f02d0 ""
#15 0x000055555a58dc81 in VM_Boot_DOSBox_Kernel () at sdlmain.cpp:7391
No locals.
#16 0x000055555a2cf7ef in BIOS::cb_bios_boot__func () at bios.cpp:9817
No locals.
#17 0x0000555558d08131 in Normal_Loop () at dosbox.cpp:373
        p_last_callback = 0
        blah = 0
        saved_allow = false
        ret = 31
        pf = @0x555561627e84: {<std::exception> = {_vptr.exception = 0x0}, lin_addr = 0, page_addr = 0, faultcode = 0}
        gpf = @0x555561627e78: {<std::exception> = {_vptr.exception = 0x0}, <No data fields>}
        x = 21845
#18 0x0000555558d089af in DOSBOX_RunMachine () at dosbox.cpp:632
        ret = 140737488332256
        p_last_callback = 0
#19 0x000055555a5bc5ef in main (argc=13, argv=0x7fffffffe918) at sdlmain.cpp:9292
        res_path = "/usr/share/dosbox-x/"
        dos_kernel_shutdown = false
        config_path = "/home/grapeli23/.config/dosbox-x/"
        config_combined = ""
        text = "Mapper-defined"
        found = 18446744073709551615
        reboot_machine = false
        tmp = "dosbox-x-2022.12.26.conf"
        videodriver = ""
        mapper_keybind = "F12"
        reboot_dos = false
        run_machine = false
        wait_debugger = false
        name = "slot9"
        x = 32767
        com_line = {opt_gnu_getopt_singlechar = "", opt_scan = <error: Cannot access memory at address 0x2>, opt_eat_argv = false, 
          cmds = std::__cxx11::list = {[0] = "quit", [1] = "warning=false"}, file_name = "/tmp/dosbox-x/src/dosbox-x", 
          raw_cmdline = "-set dosbox quit warning=false -set hma=false -c mount c /tmp/dos/DaysofTh -c c: -c @dot /a", 
          opt_style = CommandLine::either_except}
        myconf = {cmdline = 0x7ffff5800030, sectionlist = std::__cxx11::list = {[0] = 0x60c000000880, [1] = 0x60c000001540, [2] = 0x60c000001600, 
            [3] = 0x60c000002080, [4] = 0x60c000002500, [5] = 0x60c000002a40, [6] = 0x60c000002e00, [7] = 0x60c000003040, [8] = 0x60c000003100, 
            [9] = 0x60c000003400, [10] = 0x60c0000034c0, [11] = 0x60c000003b80, [12] = 0x60c000003c40, [13] = 0x60c000003d00, [14] = 0x60c000003dc0, 
            [15] = 0x60c000003e80, [16] = 0x60c000003f40, [17] = 0x60c000004000, [18] = 0x60c0000040c0, [19] = 0x60c000004180, [20] = 0x60c000004240, 
            [21] = 0x60c0000049c0, [22] = 0x60c000004a80, [23] = 0x60c000004e40, [24] = 0x60c000005b00, [25] = 0x60c000005bc0, [26] = 0x60c000005c80, 
            [27] = 0x60c000005ec0, [28] = 0x60c000006400, [29] = 0x60c000006640, [30] = 0x60c000006700, [31] = 0x60c0000067c0, [32] = 0x60c000006880, 
            [33] = 0x60c000006940, [34] = 0x60c000006a00, [35] = 0x60c000006ac0, [36] = 0x60c000006b80, [37] = 0x60c000006c40, [38] = 0x60c000006d00, 
            [39] = 0x608000002420}, secure_mode = false, initialised = false, auto_bat_additional = std::vector of length 0, capacity 0, 
          startup_params = std::vector of length 13, capacity 16 = {"/tmp/dosbox-x/src/dosbox-x", "-set", "dosbox", "quit", "warning=false", "-set", 
            "hma=false", "-c", "mount c /tmp/dos/DaysofTh", "-c", "c:", "-c", "@dot /a"}, configfiles = std::vector of length 0, capacity 0, 
          opt_editconf = "", opt_opensaves = "", opt_opencaptures = "", opt_lang = "", opt_machine = "", 
          config_file_list = std::vector of length 0, capacity 0, opt_o = std::vector of length 0, capacity 0, 
          opt_c = std::vector of length 3, capacity 4 = {"mount c /tmp/dos/DaysofTh", "c:", "@dot /a"}, 
          opt_set = std::vector of length 2, capacity 2 = {"dosbox", "hma=false"}, opt_time_limit = -1, opt_promptfolder = 0 '\000', 
          opt_disable_dpi_awareness = false, opt_disable_numlock_check = false, opt_date_host_forced = false, opt_used_defaultdir = false, 
          opt_alt_vga_render = false, opt_defaultmapper = false, opt_fastbioslogo = false, opt_break_start = false, opt_erasemapper = false, 
          opt_resetmapper = false, opt_startmapper = false, opt_defaultconf = false, opt_noautoexec = false, opt_securemode = false, 
          opt_fullscreen = false, opt_fastlaunch = false, opt_showcycles = false, opt_earlydebug = false, opt_logfileio = false, 
          opt_noconsole = false, opt_eraseconf = false, opt_resetconf = false, opt_printconf = false, opt_logint21 = false, opt_display2 = false, 
          opt_userconf = false, opt_noconfig = false, opt_log_con = false, opt_console = false, opt_startui = false, opt_silent = false, 
          opt_showrt = false, opt_nomenu = false, opt_prerun = false, opt_langcp = false, opt_debug = false, opt_nogui = false, opt_nolog = false, 
          opt_exit = false, opt_test = false}
        saved_opt_test = false
        exepath = "/tmp/dosbox-x/src/"
        workdiropt = "default"
        workdirdef = ""
        st = {st_dev = 0, st_ino = 0, st_nlink = 0, st_mode = 0, st_uid = 0, st_gid = 0, __pad0 = 0, st_rdev = 0, st_size = 0, st_blksize = 0, 
          st_blocks = 0, st_atim = {tv_sec = 0, tv_nsec = 0}, st_mtim = {tv_sec = 0, tv_nsec = 0}, st_ctim = {tv_sec = 0, tv_nsec = 0}, 
          __glibc_reserved = {0, 0, 0}}
        workdirsave = 0
        workdirsaveas = ""
maron2000 commented 1 year ago

I don't know how it actually should be fixed, but the following patch seems to work.

diff --git a/src/hardware/timer.cpp b/src/hardware/timer.cpp
index 80c307a52..3225de5d5 100644
--- a/src/hardware/timer.cpp
+++ b/src/hardware/timer.cpp
@@ -324,7 +324,9 @@ static void PIT0_Event(Bitu /*val*/) {
            LOG_MSG("PIT0_Event timing error %.6fms",err);
 #endif

-       PIC_AddEvent(PIT0_Event,pit[0].delay - (err * 0.05));
+       //PIC_AddEvent(PIT0_Event,pit[0].delay - (err * 0.05));
+       PIC_AddEvent(PIT0_Event,pit[0].delay);
+
    }
 }
grapeli commented 1 year ago

I confirm with this fix leaving Days of Thunder allows you to continue running in dosbox-x without any complications.

Hopefully this minor change to timer.cpp won't cause any regressions.

maron2000 commented 1 year ago

@grapeli Thanks for testing. Since it seems the problem is that the interval of PIC_AddEvent() is negative, I amended the patch as follows so that the original code will be valid if not negative, which should be so in majority of cases.

diff --git a/src/hardware/timer.cpp b/src/hardware/timer.cpp
index 80c307a52..aadadce8c 100644
--- a/src/hardware/timer.cpp
+++ b/src/hardware/timer.cpp
@@ -324,6 +324,10 @@ static void PIT0_Event(Bitu /*val*/) {
            LOG_MSG("PIT0_Event timing error %.6fms",err);
 #endif

+        if(pit[0].delay - (err * 0.05) <= 0) {
+            err = 0;
+            //LOG_MSG("PIT0_Event delay value negative, reset to 0", err);
+        }
         PIC_AddEvent(PIT0_Event,pit[0].delay - (err * 0.05));
    }
 }
grapeli commented 1 year ago

@maron2000 This fix is just as effective.

Problems that appear after leaving this game appeared at the time of changes in the timer.cpp code between versions 0.82.14 and 0.82.15. DOSBox-X 0.82.14 behaves correctly after finishing Days of Thunder. Incorrect in version 0.82.15. Those huge changes to the timer.cpp code introduced a lot of regressions that are discovered and unscrewed years later.

3365 - Lemmings

Patches, in turn, generate others.

3380 - Classic Jumpman