Mail Archives: djgpp-workers/1996/10/03/03:02:12
On Sun, 29 Sep 1996, DJ Delorie wrote:
> > So the call to `atexit' on go32/dpmiexcp.c should be also undone. I can
> > submit the patches if necessary.
>
> Correct, and a forced call put into _exit.
Here are the necessary patches to make a call to `abort' safe in nested
programs. I also added a small test program to `abort.c' (which is
otherwise unchanged) so you can see the difference before and after
applying the patches.
Since the original `_exit' was an assembly function on `crt0.s', I
preferred not to mess with it; so I just renamed it to `__exit'
(`___exit' in assembly) and added `_exit' to go32/dpmiexcp.c. I
understand that dpmiexcp is always linked in, so that shouldn't be a
problem. Am I right on this?
Charles, would you please also take a look at these changes to see if I
didn't screw anything? Thanks.
*** src/libc/crt0/crt0.s~0 Thu Jan 25 02:54:12 1996
--- src/libc/crt0/crt0.s Wed Oct 2 10:36:46 1996
***************
*** 275,283 ****
#define FREESEL(x) movw x, %bx; movw $0x0001, %ax; int $0x31
! .global __exit
.align 2
! __exit:
movb 4(%esp), %al
exit:
movb %al, %cl
--- 275,283 ----
#define FREESEL(x) movw x, %bx; movw $0x0001, %ax; int $0x31
! .global ___exit
.align 2
! ___exit:
movb 4(%esp), %al
exit:
movb %al, %cl
***************
*** 297,303 ****
int $0x31 /* Free block and selector */
#ifdef MULTIBLOCK
9: movl ___djgpp_memory_handle_pointer, %ebx
! movl $__exit, %esp /* We will free stack! Old init code as temp stack */
jmp 7f
6: subl $8, %ebx
movl (%ebx), %edi
--- 297,303 ----
int $0x31 /* Free block and selector */
#ifdef MULTIBLOCK
9: movl ___djgpp_memory_handle_pointer, %ebx
! movl $___exit, %esp /* We will free stack! Old init code as temp stack */
jmp 7f
6: subl $8, %ebx
movl (%ebx), %edi
*** src/libc/crt0/crt0.t~2 Tue Aug 13 19:20:38 1996
--- src/libc/crt0/crt0.txh Wed Oct 2 11:23:00 1996
***************
*** 110,119 ****
@subheading Description
This function exits the program, returning @var{exit_code} to the
! calling process. No additional processing is done, and any
! @code{atexit} functions are not called. This function is normally
! called only by @code{exit}. Since this does not unhook hardware
! interrupts, this can cause crashes after the program exits.
@subheading Return Value
--- 110,144 ----
@subheading Description
This function exits the program, returning @var{exit_code} to the
! calling process. No additional processing (such as closing file
! descriptors or calls to the static destructor functions) is done, and
! any @code{atexit} functions are not called; only the hardware interrupt
! handlers are unhooked, to prevent system crashes e.g. after a call to
! @code{abort}. This function is normally called only by @code{exit} and
! @code{abort}.
!
! @subheading Return Value
!
! This function does not return.
!
! @c ----------------------------------------------------------------------
! @node __exit, process
! @subheading Syntax
!
! @example
! #include <stdlib.h>
!
! void __exit(int exit_code);
! @end example
!
! @subheading Description
!
! This is an internal library function which exits the program, returning
! @var{exit_code} to the calling process. No additional processing is
! done, and any @code{atexit} functions are not called. Since hardware
! interrupts are not unhooked, this can cause crashes after the program
! exits. This function is normally called only by @code{_exit}; do
! @emph{not} call it directly.
@subheading Return Value
*** src/libc/go32/dpmiexcp.c~1 Sat May 4 19:09:44 1996
--- src/libc/go32/dpmiexcp.c Wed Oct 2 10:32:42 1996
***************
*** 318,324 ****
__dpmi_paddr except;
__dpmi_meminfo lockmem;
int i;
- static int veryfirst = 1;
for (i = 0; i < SIGMAX; i++)
signal_list[i] = (SignalHandler)SIG_DFL;
--- 318,323 ----
***************
*** 358,367 ****
__dpmi_get_protected_mode_interrupt_vector(9, &__djgpp_old_kbd);
__djgpp_exception_toggle(); /* Set new values & save old values */
- if (veryfirst) {
- veryfirst = 0;
- atexit(__djgpp_exception_toggle); /* Toggle at exit */
- }
/* get original video mode and save */
old_video_mode = _farpeekb(_dos_ds, 0x449);
}
--- 357,362 ----
***************
*** 375,378 ****
--- 370,386 ----
else
__djgpp_hwint_flags |= 1;
return oldenable;
+ }
+
+ void __attribute__((noreturn))
+ _exit(int status)
+ {
+ /* We need to restore hardware interrupt handlers even if somebody calls
+ `_exit' directly, or else we crash the machine in nested programs.
+ We only toggle the handlers if the original keyboard handler is intact
+ (otherwise, they might have already toggled them). */
+ if (__djgpp_old_kbd.offset32 == kbd_ori.offset32
+ && __djgpp_old_kbd.selector == kbd_ori.selector)
+ __djgpp_exception_toggle ();
+ __exit (status);
}
*** src/libc/ansi/stdlib/abort.c~0 Thu Apr 13 09:21:48 1995
--- src/libc/ansi/stdlib/abort.c Wed Oct 2 11:06:30 1996
***************
*** 11,13 ****
--- 11,51 ----
_write(STDERR_FILENO, msg, sizeof(msg)-1);
_exit(1);
}
+
+ #ifdef TEST
+
+ #include <stdio.h>
+ #include <errno.h>
+ #include <string.h>
+ #include <process.h>
+ #include <sys/exceptn.h>
+
+ int main (int argc, char *argv[])
+ {
+ int status = 0;
+
+ errno = 0;
+ if (argc > 1)
+ {
+ if (strcmp (argv[1], "abort") == 0)
+ abort ();
+ else if (strcmp (argv[1], "toggle") == 0)
+ {
+ __djgpp_exception_toggle ();
+ abort ();
+ }
+ }
+ else
+ {
+ fprintf (stderr, "\tType `%s abort RET'\n"
+ "or\n"
+ "\t `%s toggle RET'\n", argv[0], argv[0]);
+ status = system ("");
+ }
+
+ fprintf (stderr, "Child returned %d\n", status);
+ if (errno)
+ perror ("spawn");
+ return 0;
+ }
+ #endif
- Raw text -