From: jdickson@jato.jpl.nasa.gov (Jeff Dickson)
Subject: Re: InputHandler debugging (long)
Organization: Jet Propulsion Laboratory
Date: Wed, 16 Dec 1992 03:35:08 GMT

tomme@Minsk.docs.uu.se (Thomas Holmstr|m) writes:




>I am having some trouble with a piece of code which will be hooked into
>the input handler list. The program always crash on the Signal() (1*) in the
>handler routine when I push a key. It works fine if I comment out the
>Signal() (ie. it doesn't do *anything* until I break it). I can send the
>task the signal from Xoper and that works fine.
>	Part of the problem is that I cannot find a good way of debugging
>interrupts. I don't have any streams to write info to, do I? I've looked
>at similar code hooking into the input handler list and I think I do
>that the right way. Sorry for the somewhat log posting, I don't think
>I could make it any shorter and still keep the relevant parts in.
>	I'm using Dice, the registered version, and since it supports
>registered arguments I really would like to use that instead of an
>assembler routine, but when I declare the function as __regargs the reference
>at (2*) uses _InputHandler (or _C_InputHandler) when it should be
>@InputHandler. I've tried to redefined the Interrupt struct as
>> struct Interrupt {
>>    struct  Node is_Node;
>>    APTR    is_Data;
>>    VOID    (__regargs)(*is_Code)();}
>or something like that (I'm not at my computer right now). How to do this?


>Thanks in advance for any comments and/or suggestions.


>The program:
>/************************* Global declarations ***************************/
>struct HandlerData {
>  struct MsgPort *parentport;
>  struct Task *parenttask;
>  ULONG unblanksig;
>} handlerdata;
>struct Process *process;
>ULONG handlersig, timersig, unblanksig;

>/*********************** Main function ************************/
>void main(void) {
>  init();
>  while(locked) {
>    ULONG wsigs = handlersig | timersig | unblanksig | SIGBREAKF_CTRL_C;
>    signals = Wait(wsigs);
>    if(signals & SIGBREAKF_CTRL_C) {
>	/* Cleanup and exit */
>    }
>    if(signals & handlersig) {
>	/* Handle message */
>    }
>    if(signals & timersig) blank();
>    if(signals & unblanksig) unblank();
>  }
>  cleanup();
>}

>/*********************** Init code **************************/
>[...]
>  if(!(process = (struct Process *)FindTask(NULL))) {
>	/* Error */
>  }
>[...]
>  if(!(handlerport = CreatePort(HPORT_NAME, HPORT_PRI))) {
>	/* Error */
>  }
>  handlersig = (1 << (handlerport->mp_SigBit));
>[...]
>  if((usignr = AllocSignal(-1)) == -1) {
>	/* Error */
>  }
>  unblanksig = (1 << usignr);
>[...]
>  inputreq->io_Command = IND_ADDHANDLER;
>  inputreq->io_Data = &interrupt;
>  interrupt.is_Node.ln_Pri = HANDLER_PRI;	/* #defined as 10 */
>  handlerdata.parentport = handlerport;
>  handlerdata.parenttask = &(process->pr_Task);
>  handlerdata.unblanksig = unblanksig;
>  interrupt.is_Data = &handlerdata;
>  interrupt.is_Code = InputHandler; /* InputHandler calls C_InputHandler (2*) */
>  if(DoIO(inputreq)) {
>	/* Error */
>  }

>/*********** Input handler, called with stack-arguments ***************/
>struct InputEvent *
>	C_InputHandler(struct InputEvent *ev, struct HandlerData *data) {
>  struct InputEvent *currev, *retev, *procev, *tmpev;
>  currev = ev; retev = procev = NULL;
>  while(currev) {
>    tmpev = currev->ie_NextEvent;
>    switch(currev->ie_Class) {
>      case IECLASS_RAWKEY :
>      case IECLASS_RAWMOUSE :
>	Signal(data->parenttask, data->unblanksig);  /* Crash here!! (1*) */
>	break;
>      default :
>    }
>    currev = tmpev;
>  }
>  return ev;
>}

>/*********** _InputHandler called with register arguments *************/
>		xref	_C_InputHandler
>		xdef	_InputHandler
>_InputHandler:	movem.l	A0/A1,-(A7)
>		jsr     _C_InputHandler
>		addq.l	#8,A7
>		rts
>		end
>--
>_/_/_/_/_/   _/    _/         Thomas  Holmstr|m
>   _/       _/_/_/_/        tomme@Student.docs.uu.se
>  _/       _/    _/            +46 18 261628
> _/       _/    _/   DVL, University of Uppsala, Sweden

	The one thing I notice off the bat is that you are not restoring
the data segment in the Input handler code. The function Signal(), for
example, needs the base of the exec library and the stub code (or what-
ever) expects to find it in the global variable _SysBase. The variable
SysBase is known to the compiler as some offset from the base of the
data segment. Since you're not restoring it in the Input handler code,
Signal() is assuming absolute garbage as the pointer to the base of the
exec library and hence - CABLOOEY!

Jeff

Xref: sparky comp.sys.amiga.programmer:17555 comp.sys.amiga.hardware:21796