Mail Archives: djgpp-workers/1997/05/15/13:22:59
I got intimidated by this bug too much, so I investigated it a bit more,
and I think I've found a solution.
For those who might not know what it is all about, try running the
following Makefile:
test-coff:
foo
bar
Where `foo' and `bar' are two different raw COFF images (make sure
foo.exe and bar.exe are nowehere on your PATH). Say "make [Enter]", then
quickly press any key and hold it. Your machine will crash, at least if
you use CWSDPMI.
I think I know the reason. When you invoke a raw COFF image, go32-v2 is
called to run it (since DOS doesn't know about COFF). go32-v2 uses
v2loadimage to load it, then longjmp's to the startup code of the loaded
image. The startup code hooks the keyboard interrupt (to support SIGINT),
then runs the program. When the program exits, it restores the previous
keyboard handler, which is the go32-v2's handler (installed by it when it
started). Normally, a nested program would return to its parent
(go32-v2), so when the parent exits, it will in its turn restore the
original handler (in the BIOS). However, in the case of v2loadimage, the
thread never returns to go32-v2; instead, the loaded image exits directly
to DOS, and the keyboard interrupt is left pointing to the place where
go32-v2's handler once was. The rest is history, as they say.
Does the above make any sense at all? Charles? If it does, then I think
the simple patch below will take care of this. After applying it, I
couldn't crash my system with the above Makefile no matter how hard did I
try.
Btw, if you are wondering how come the debuggers don't crash your system
after you exit them, it's because the debuggers install a protected-mode
handler for Int 21h so that when the debuggee exits with Int 21h/AH=4Ch,
the debugger gets control and cleans up. Go32-v2 doesn't do that.
The patch follows:
*** src/stub/go32-v2.c~0 Tue Aug 13 02:57:02 1996
--- src/stub/go32-v2.c Mon May 12 15:09:52 1997
***************
*** 1,3 ****
--- 1,4 ----
+ /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
/* GO32V2 - A quick hack for loading non-stubbed images for V2.0
***************
*** 6,11 ****
--- 7,14 ----
Eli Zaretskii 7/96 fix code which runs V2 COFF.
Eli Zaretskii 8/96 *really* fix code which runs V2 COFF;
support for V2.1 long command lines.
+ Eli Zaretskii 5/97 toggle exceptions before longjmp to V2 COFF,
+ so they are restored correctly on exit.
Bugs: doesn't scan manifest for versions installed yet */
/* If you want to change this, remember to test it with all the
*************** run_v2_coff(int argc, char **argv)
*** 373,379 ****
--- 376,388 ----
}
argv[0] = argv0;
+ /* Since the thread won't ever return to us, our exit code won't
+ get a chance to revert the exception and hardware interrupt
+ handlers to their original values. So do it now; otherwise,
+ the exceptions will point to nowhere when the loaded image exits. */
+ __djgpp_exception_toggle ();
longjmp(start_state, 0);
+ __djgpp_exception_toggle (); /* not necessary, but... paranoia. */
return 0;
}
*************** main(int argc, char **argv)
*** 457,463 ****
if (argc < 1)
{
! printf("go32/v2 version %s built %s %s\n","2.0",__DATE__,__TIME__);
printf("Usage: go32 coff-image [args]\n");
printf("Rename this to go32.exe only if you need a go32 that can run v2 binaries as\n"
" well as v1 binaries (old makefiles). Put ahead of the old go32 in your PATH\n"
--- 466,472 ----
if (argc < 1)
{
! printf("go32/v2 version %s built %s %s\n","2.1a",__DATE__,__TIME__);
printf("Usage: go32 coff-image [args]\n");
printf("Rename this to go32.exe only if you need a go32 that can run v2 binaries as\n"
" well as v1 binaries (old makefiles). Put ahead of the old go32 in your PATH\n"
- Raw text -