[fpc-devel]FW: Help! Walking stack causes GPF?

Romio romio at mastak.com
Wed Sep 13 23:30:48 CEST 2000


Hi, folks!

i've received following email and decide to forward it to mailing list.
as you'll understand, you'll need answer it directly into email of that guy,
instead of mailing list.

-----FW: <39BF8A02.3520B4DD at geocities.com>-----

Date: Wed, 13 Sep 2000 14:06:58 +0000
Sender: root at smv12.iname.net
From: startx <startx at geocities.com>
To: romio at iname.com
Subject: Help! Walking stack causes GPF?

Hi,

I am getting into serious troubles with my work (and my boss). Please
help me!
I've tried to mail the fpc mailing list, but my SMTP server refuses to
send... don't know why - so excuse me if I write to you directly.

I am writing a pseudo multitasking application under free-pascal/DOS
(go32), as I need the equivalent of cooperative multitasking.

The idea I've took is simple: every program to be multiplexed is put in
a unit, and the inizialization part only contains a call to a
registering function:

        Unit something;
        interface
        implementation
        Uses .....

        procedure MAIN;
        begin
          ...
          Multiplex;    // call to let other pseudoprograms run
          ...
          Multiplex;
          ...
        end;

        begin           // initialization
          addapplic('SOMETHING', at main,16384)
        end.

The last line adds a record in a linked list which records the name,
entry-point and stack size.

When this unit has to be run, a procedure is called which getmem() the
stack, puts a termination address, then the address of the procedure
MAIN above, a suitable EBP and then exits normally. This has the effect
of jumping at MAIN with a new stackframe. This procedure "Newtask" also
appends a new slot for the scheduler.

  with thisnewtask^ do begin
    getmem(stack,dimst);
    pnt := pointer(longint(@stack)+dimst-4);    // point to last
doubleword of this stack
    pnt^ := @TerminateProg;                     // push the address of a
termination routine (cleanup)
    dec(longint(pnt),4);
    pnt^ := entrypoint;                         // push the address of
the newly created thread
    dec(longint(pnt),4);
    pnt^ := pointer(longint(@stack)+dimst);     // ESP of this new
process
    pbp  := pnt;        // every process has a pbp member, which points
into its stack
  end;

When procedure Multiplex is called, it searches for a new slot, then
moves the BP of the new process into the 'real' EBP and returns. This
jumps where that process was left over, which the same stack:

  // save the stackframe of the calling pseudoprocess...
  asm
    mov   edi,Actprog                   // ActProg points to infos about
the current process
    mov   [edi].TProgram.pbp,ebp        // which is about to be
suspended right now
  end;

  // search for the next process to time-slice...
  ...
  // found. Now Actprog points to the new process
  asm
    mov   edi,Actprog
    mov   ebp,[edi].TProgram.pbp        // another stack is now in
effect
  end


Now, everything works just fine, but the program runs for some minute,
and then does a GPF. I'm pretty sure the code is OK (no memory
overwrites and the like), so I suspect this 'walking stack' cause some
other problem. Often the program crashes when trying to allocate or
fremem() some memory. When it tries to do a getmem(apointer,8192),
nothing can be wrong in the code, right? As long as the pointer
'apointer' resides somewhere in the DS segment, nothing should go wrong.
Well, often (but not always) the program give me this GPF. Even the
errors are not always the same... nor the point in code and nor the
moment. May be the program lasts just one minute, or ten. There are
*never* other kinds of problems (which could make me suppose my code has
bugs).

I have also to add that it seems that in a Linux dosbox everything
(ppc386, gdbpas) works better (I tried to debug the code, but often
gdbpas hangs the machine in true dos; it never hangs in a linux dosbox
(dosemu).

This leads me to think there's something wrong, or something I should
know, about CWSDPMI.EXE. I have also tried to lock_data in the stack,
but seems nothing changes. Often happens that I compile the above
program, put a breakpoint somewhere, and run it: the computer locks.
>From that point, the same executable becomes undebuggable - if any
breakpoint is set (even *before* the stack trick), using either IDE or
gdbpas, everything locks. So it is hard to debug, sometimes.
If I try to debug in a Linux box, I succed, but it is too slow
(graphics...) to work comfortably.

Last thing to add: I use Graph, and do an int $33 to poll the mouse. No
other strange things are done. It seems also that in a win98 command
prompt, instead of pure dos, things get slightly better (but not so
much).

I can email the entire source (it is a little long indeed), if
requested.
Again, please help me - I have no more than a week, and after then I
must face my boss and our customer...

Thank you.

Doriano Bengino
startx at geocities.com
linuxfan at tin.it

--------------End of forwarded message-------------------------

---
with best regards, Romio "Lucky" Pedchenko :) // romio at mastak.com
look here: http://clc.uch.net/ftn/fidosoft.html




More information about the fpc-devel mailing list