Skip to content

Set return code at beginning of termination function #20

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 11, 2024
Merged

Conversation

nmlgc
Copy link
Contributor

@nmlgc nmlgc commented May 10, 2024

DOSBox also sets it before any other checks or assignments. Required for Turbo C++ 4.0J's TCC.EXE and TLINK.EXE to correctly return their exit code to the host OS, and to build systems that rely on non-zero exit codes to indicate failure.

Once again, the actual cause behind the bug is more complicated:

  • Both TCC and TLINK spawn RTM.EXE as a TSR.
  • This TSR offers various helper functions that run using the PSP of the RTM.EXE process. This is done by overriding the current PSP using INT 21h, AH=50h and resetting it to its original value before returning.
  • RTM.EXE also properly terminates itself via INT 21h, AH=4C shortly before the parent process does.
  • This means that msdos_process_terminate() gets called three times:
    • Call 1) TSR's RTM,
    • call 2) exits RTM with exit code 0, and
    • call 3) terminates the parent process with the intended exit code.
  • msdos_process_terminate() always frees the process entry, even in the function's TSR mode.
  • Three terminations for two processes mean that call 3) will always fail with a throw(0x1f); and not run to the bottom of the function where retval is set. Therefore, retval stays at the 0 set during call 2), ignoring the actually intended exit code.
  • Just leaking the process entry won't fix this issue due to the way the PSP is continuously overridden:
    • MS-DOS Player's implementation of INT 21h, AH=50h permanently changes the PSP of the process entry.
    • This causes both the parent's and RTM's entry to both point to RTM's PSP during RTM function calls.
    • Since RTM's termination must be run with RTM's PSP as the active one, RTM doesn't get to revert this final temporary PSP change.
    • This leaves the parent's PSP permanently set to RTM's PSP, …
    • …causing call 3) to never actually target the parent process.
  • It would work if we also simplified msdos_int_21h_50h() to a single current_psp = CPU_BX; assignment, matching regular DOS. But that's two workarounds instead of one.

In the long term, we probably want to remove the process_t structure and only emulate its fields in terms of the single SDA and multiple PSP structures. For example, MS-DOS exclusively keeps a process's maximum number of files in the PSP, not in any separate process structure. Just like the new_process allocation hacks, process_t also dates back to the very first build from 2010, and looks like an equally temporary hack.

DOSBox also sets it before any other checks or assignments. Required
for Turbo C++ 4.0J's `TCC.EXE` and `TLINK.EXE` to correctly return
their exit code to the host OS, and to build systems that rely on
non-zero exit codes to indicate failure.
@cracyc cracyc merged commit 5ac8c4d into cracyc:vt May 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants