delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2001/05/23/15:32:01

Date: Wed, 23 May 2001 21:46:24 +0300
From: "Eli Zaretskii" <eliz AT is DOT elta DOT co DOT il>
Sender: halo1 AT zahav DOT net DOT il
To: djgpp-workers AT delorie DOT com
Message-Id: <4331-Wed23May2001214623+0300-eliz@is.elta.co.il>
X-Mailer: Emacs 20.6 (via feedmail 8.3.emacs20_6 I) and Blat ver 1.8.9
CC: Charles Sandmann <sandmann AT clio DOT rice DOT edu>
Subject: Crashes due to selector depletion
Reply-To: djgpp-workers AT delorie DOT com

I got annoyed by crashes of large nested jobs on Windows enough to
want to make the program exit more gracefully instead of crashing the
DOS box.

The problem is that Windows leaks descriptors, and we finally get to a
situation where we cannot allocate a descriptor for _dos_ds.  The
startup code does this (in crt1.c):

    void
    __crt1_startup(void)
    {
      __bss_count ++;
      __crt0_argv = 0;
      setup_os_version();
      setup_core_selector();
      setup_screens();
      setup_go32_info_block();

Here's the beginning of setup_core_selector:

    static void
    setup_core_selector(void)
    {
      int c = __dpmi_allocate_ldt_descriptors(1);
      if (c == -1)
      {
	_dos_ds = 0;
	return;
      }

What happens is exactly that: __dpmi_allocate_ldt_descriptors fails,
and we set _dos_ds to zero.  The very next thing is the call to
setup_screens, which does this:

    static void
    setup_screens(void)
    {
      if(_farpeekw(_dos_ds, 0xffff3) == 0xfd80)	/* NEC PC98 ? */
      {
	ScreenPrimary = ScreenSecondary = 0xa0000;
      }
      else if (_farpeekb(_dos_ds, 0x449) == 7)
      {
	ScreenPrimary = 0xb0000;
	ScreenSecondary = 0xb8000;
      }

This uses _dos_ds, so we are toast: the program GPFaults, usually
taking the DOS box with it ("This program performed an illegal
operation and will be terminated...").

I don't want to get fancy here, just print some legible message and
exit.  But it ain't easy: without _dos_ds set, we cannot use dosmemput
and such likes to put the message text into the transfer buffer.  A
bummer.

One possible way out of this is to use the selector for the program's
environment block.  This selector is created by the DPMI host when the
stub calls the PM entry point, and we actually use it in the startup
code, to fetch the environment strings.

(I originally considered to use the PSP selector, since the transfer
buffer follows the PSP, but that selector seems to have a 100h-byte
limit, or at least could be like that according to the DPMI spec.)

Question: is it safe to overwrite the program's environment by using
the environment block as the transfer buffer?  Note that I don't want
to modify the selector itself -- this is verboten by the DPMI rules --
only to write over the environment strings accessing them via the
selector stuffed by the DPMI host at offset 2Ch in the PSP.

Thanks in advance for any advice.

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019