home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / sd386v50.zip / sd386src.zip / DBGQ.C < prev    next >
Text File  |  1996-05-09  |  50KB  |  1,054 lines

  1. /*****************************************************************************/
  2. /* File:                                             IBM INTERNAL USE ONLY   */
  3. /*                                                                           */
  4. /*   dbgq.c                                                                  */
  5. /*                                                                           */
  6. /* Description:                                                              */
  7. /*                                                                           */
  8. /*   Queue handling for the debugger.                                        */
  9. /*                                                                           */
  10. /* History:                                                                  */
  11. /*                                                                           */
  12. /*   06/08/94 Created.                                                       */
  13. /*                                                                           */
  14. /*****************************************************************************/
  15.  
  16. #include "all.h"
  17.  
  18. static PSZ     DbgQueBaseName = "\\QUEUES\\DbgQue";
  19. static char    DbgQueName[32];
  20. static BOOL    ReadQueReady;
  21. static BOOL    AllDbgsAreDeadFlag;
  22. static int     RestartInstance;
  23.  
  24. void    SetDbgQueName( char *pQueName ) { strcpy(DbgQueName, pQueName); }
  25. BOOL    AllDbgsAreDead( void ) { return(AllDbgsAreDeadFlag);}
  26. void    ResetAllDbgsAreDeadFlag( void ) { AllDbgsAreDeadFlag=FALSE;}
  27.  
  28. /*****************************************************************************/
  29. /* StartDbgQue()                                                             */
  30. /*                                                                           */
  31. /* Description:                                                              */
  32. /*                                                                           */
  33. /*  Start up a que to handle SD386 messages.                                 */
  34. /*                                                                           */
  35. /* Parameters:                                                               */
  36. /*                                                                           */
  37. /* Return:                                                                   */
  38. /*                                                                           */
  39. /*  rc    System API return code.                                            */
  40. /*                                                                           */
  41. /* Assumptions:                                                              */
  42. /*                                                                           */
  43. /*****************************************************************************/
  44. APIRET StartDbgQue( void )
  45. {
  46.  APIRET rc;
  47.  char    PidString[12];
  48.  TIB    *pTib;
  49.  PIB    *pPib;
  50.  USHORT  ThisPid;
  51.  
  52.  /****************************************************************************/
  53.  /* - Get the pid of this probe and use it to define a unique name.          */
  54.  /* - Stuff in the base que name.                                            */
  55.  /* - Concatenate the pid to make the name unique for the system.            */
  56.  /****************************************************************************/
  57.  DosGetInfoBlocks(&pTib, &pPib);
  58.  ThisPid = (USHORT)pPib->pib_ulpid;
  59.  
  60.  memset(DbgQueName, 0, sizeof(DbgQueName));
  61.  strcat(DbgQueName, DbgQueBaseName);
  62.  
  63.  memset(PidString, 0, sizeof(PidString));
  64.  RestartInstance++;
  65.  sprintf( PidString, "%d-%d", ThisPid, RestartInstance );
  66.  strcat(DbgQueName, PidString );
  67.  
  68.  /****************************************************************************/
  69.  /* - Set a flag to wait on indicating that the queue thread is ready to     */
  70.  /*   read.                                                                  */
  71.  /****************************************************************************/
  72.  ReadQueReady = FALSE;
  73.  
  74.  rc = StartQue(DbgQueName, ReadDbgQue);
  75.  if(rc) return(rc);
  76.  
  77.  /****************************************************************************/
  78.  /* - Wait until the queue is ready to read.                                 */
  79.  /****************************************************************************/
  80.  while( ReadQueReady == FALSE ) DosSleep(100);
  81.  return( 0 );
  82. }
  83.  
  84. /*****************************************************************************/
  85. /* ReadDbgQue()                                                              */
  86. /*                                                                           */
  87. /* Description:                                                              */
  88. /*                                                                           */
  89. /*   Read and handle SD386 queue messages. This function runs                */
  90. /*   in its own thread in a do forever loop.                                 */
  91. /*                                                                           */
  92. /* Parameters:                                                               */
  93. /*                                                                           */
  94. /*   qHandle        -> to the queue handle. This is passed in by the         */
  95. /*                     StartQue() function when the queue is created.        */
  96. /*                                                                           */
  97. /* Return:                                                                   */
  98. /*                                                                           */
  99. /*  void                                                                     */
  100. /*                                                                           */
  101. /* Assumptions:                                                              */
  102. /*                                                                           */
  103. /*****************************************************************************/
  104. void ReadDbgQue( void *qHandle)
  105. {
  106.  APIRET       rc;
  107.  REQUESTDATA  Request;
  108.  ULONG        DataLen;
  109.  BYTE         ElePri;
  110.  BOOL         EndThread = FALSE;
  111.  LHANDLE      LsnHandle = 0;
  112.  ALLPIDS     *p;
  113.  BOOL         TorF;
  114.  USHORT       pid;
  115.  int          ListenThreadID = 0;
  116.  LHANDLE      QueHandle;
  117.  
  118.  DBG_QUE_ELEMENT *pDataAddr=NULL;
  119.  
  120.  
  121.  if( IsVerbose() ) {printf("\nDbg Que Started");fflush(0);}
  122.  /****************************************************************************/
  123.  /* - The queue has its own handle for communications between itself and     */
  124.  /*   the probe que. When connected serially, then there is only one handle  */
  125.  /*   and it must be shared by all dbg/esp connections.                      */
  126.  /****************************************************************************/
  127.  if( (SerialParallel() == SERIAL) )
  128.   LsnHandle = GetComHandle();
  129.  
  130.  QueHandle    = (LHANDLE)qHandle;
  131.  
  132.  /****************************************************************************/
  133.  /* - The queue thread needs to be started and ready to read before          */
  134.  /*   the StartQue() call completes. The StartQue() waits for the            */
  135.  /*   following flag to be set before returning its caller.                  */
  136.  /****************************************************************************/
  137.  ReadQueReady = TRUE;
  138.  
  139.  /****************************************************************************/
  140.  /* - Start the que reading loop.                                            */
  141.  /****************************************************************************/
  142.  for(; EndThread == FALSE ;)
  143.  {
  144.   /***************************************************************************/
  145.   /* We're going to read an element from the dbg queue.  The queue is read   */
  146.   /* in FIFO order and we wait until there is a message to read.  We get an  */
  147.   /* element priority but we don't care about it.  Request.ulData contains   */
  148.   /* the message.                                                            */
  149.   /***************************************************************************/
  150.   rc = DosReadQueue(QueHandle,
  151.                     &Request,
  152.                     &DataLen,
  153.                     (PPVOID)&pDataAddr,
  154.                     QUE_FIFO,
  155.                     DCWW_WAIT,
  156.                     &ElePri,
  157.                     0L);
  158.  
  159.   /***************************************************************************/
  160.   /* - Handle the private verbose option.                                    */
  161.   /***************************************************************************/
  162.   if( IsVerbose() ) PrintDbgQueMessage( &Request );
  163.  
  164.   switch( Request.ulData )
  165.   {
  166.    /**************************************************************************/
  167.    /*  This message is added when we're trying to debug a child debugger.    */
  168.    /**************************************************************************/
  169. #if 0
  170.    {
  171.     case DBG_QMSG_REQUEST_ACCESS:
  172.      rc = DosGiveSharedMem( GetShrMem(), pDataAddr->sid, PAG_READ | PAG_WRITE );
  173.      printf("\naccess given to pid=%d rc=%d",pDataAddr->pid,rc);fflush(0);
  174.      AddDbgPidAndSid( pDataAddr->pid, pDataAddr->sid, 0 );
  175.      break;
  176.    }
  177. #endif
  178.  
  179.    case DBG_QMSG_SELECT_SESSION:
  180.     /*************************************************************************/
  181.     /* - Bring a debugger session to the foreground. This has to be done     */
  182.     /*   by the parent debugger so it's accomplished by sending this         */
  183.     /*   message to the que.                                                 */
  184.     /*************************************************************************/
  185.     p = GetPid( pDataAddr->pid );
  186.     DosSelectSession( p->DbgSid );
  187.     break;
  188.  
  189.    case DBG_QMSG_SELECT_PARENT_ESP:
  190.     /*************************************************************************/
  191.     /* - Bring the er session to the foreground. This has to be done in the  */
  192.     /*   by the parent debugger and so it's accomplished by sending this     */
  193.     /*   message to the que.                                                 */
  194.     /*************************************************************************/
  195.     p = GetPidIndex( 1 );
  196.     DosSelectSession( p->EspSid );
  197.     break;
  198.  
  199.    case DBG_QMSG_CTRL_BREAK:
  200.     if( (SerialParallel() == SERIAL) && (SingleMultiple() == MULTIPLE) )
  201.     {
  202.      /************************************************************************/
  203.      /* - Kill the polling thread if running serial.  This will guarantee    */
  204.      /*   that no other messages will be serviced during ctrl-break          */
  205.      /*   processing.                                                        */
  206.      /* - Wait for the polling thread to die.                                */
  207.      /* - Grab the serial mutex.                                             */
  208.      /************************************************************************/
  209.      SetPollingThreadFlag( THREAD_TERM );
  210.      while( GetPollingThreadFlag() != NOT_RUNNING ){ DosSleep(100) ;}
  211.      RequestSerialMutex();
  212.  
  213.      /************************************************************************/
  214.      /* - The assumption at this point is that the debugger sending the      */
  215.      /*   ctrl-break is not connected.                                       */
  216.      /* - Give the connection to the debugger that's sending the ctrl-break. */
  217.      /*   This will guarantee that the debugger thread will get the next     */
  218.      /*   access to the serial mutex.                                        */
  219.      /************************************************************************/
  220.      {
  221.       USHORT             GoToPid;
  222.       ALLPIDS           *pYield;
  223.       ALLPIDS           *pGoTo;
  224.  
  225.       pYield = GetPidConnected();
  226.  
  227.       if( pYield )
  228.       {
  229.        SetConnectSema4( &pYield->ConnectSema4, TRUE );
  230.        pYield->Connect                 = DISCONNECTED;
  231.        pYield->PidFlags.ConnectYielded = TRUE;
  232.       }
  233.  
  234.       GoToPid         = pDataAddr->pid;
  235.       pGoTo           = GetPid( GoToPid );
  236.       pGoTo->Connect  = CONNECTED;
  237.  
  238.       pGoTo->PidFlags.ConnectYielded = FALSE;
  239.  
  240.       /***********************************************************************/
  241.       /* - Set a flag to indicate whether or not the sema4 has to be opened  */
  242.       /*   before it is posted.                                              */
  243.       /* - Post the connect sema4 for this debugger.                         */
  244.       /***********************************************************************/
  245.       TorF = TRUE;
  246.       if( GoToPid == DbgGetProcessID() )
  247.        TorF = FALSE;
  248.  
  249.       PostConnectSema4( &pGoTo->ConnectSema4, TorF ); /* do not move!!!          */
  250.      }
  251.     }
  252.  
  253.     /*************************************************************************/
  254.     /* - Send the ctrl-break.                                                */
  255.     /*************************************************************************/
  256.     xSendCtrlBreak(LsnHandle, pDataAddr->pid );
  257.  
  258.     if( (SerialParallel() == SERIAL) && (SingleMultiple() == MULTIPLE) )
  259.     {
  260.      /************************************************************************/
  261.      /* - Release the serial mutex.                                          */
  262.      /* - Start the polling thread back up.                                  */
  263.      /************************************************************************/
  264.      ReleaseSerialMutex();
  265.      _beginthread( PollForMsgFromEsp, NULL, 0x8000, NULL );
  266.     }
  267.     break;
  268.  
  269.    case DBG_QMSG_OPEN_CONNECT:
  270.     /*************************************************************************/
  271.     /* - This message comes with parallel connections only.                  */
  272.     /* - A separate connection is established between the dbg and esp ques.  */
  273.     /*************************************************************************/
  274.     OpenAnotherConnection( &LsnHandle );
  275.     ListenThreadID = _beginthread(ListenForMsgFromEsp, NULL, 0x8000, (void *)LsnHandle);
  276.     break;
  277.  
  278.    case DBG_QMSG_NEW_PROCESS:
  279.     /*************************************************************************/
  280.     /* - All the probes send their new process notifications here.           */
  281.     /*************************************************************************/
  282.     {
  283.      USHORT          DbgPid;
  284.      ULONG           DbgSid;
  285.      ULONG           ErrorMsgLen;
  286.      QUE_ERR_ELEMENT Que_ErrElement;
  287.  
  288.      /************************************************************************/
  289.      /* - If debugging serial/multiple, then at this point the polling       */
  290.      /*   thread flag will be ended.                                         */
  291.      /************************************************************************/
  292.  
  293.      /************************************************************************/
  294.      /* - Add a node to the shared heap for this process.                    */
  295.      /************************************************************************/
  296.      AddPid( pDataAddr->pid,
  297.              pDataAddr->sid,
  298.              0,
  299.              pDataAddr->type,
  300.              pDataAddr->FileSpec );
  301.  
  302.      /************************************************************************/
  303.      /* - Spawn a debugger for the new process.                              */
  304.      /************************************************************************/
  305.      ErrorMsgLen = sizeof( Que_ErrElement.ErrorMsg );
  306.  
  307.      memset( Que_ErrElement.ErrorMsg, 0, ErrorMsgLen );
  308.  
  309.      rc = SpawnDbg(  pDataAddr->pid,
  310.                     &DbgPid,
  311.                     &DbgSid,
  312.                      DbgQueName,
  313.                      ErrorMsgLen,
  314.                      Que_ErrElement.ErrorMsg );
  315.  
  316.       if( rc && (rc != ERROR_SMG_START_IN_BACKGROUND) )
  317.       {
  318.        Que_ErrElement.rc = rc;
  319.  
  320.        SendMsgToDbgQue(DBG_QMSG_ERROR, &Que_ErrElement, sizeof(Que_ErrElement));
  321.       }
  322.  
  323.      /************************************************************************/
  324.      /* - Add the process id and the session id of the spawned debugger      */
  325.      /*   to the pid structure.                                              */
  326.      /************************************************************************/
  327.      AddDbgPidAndSid( pDataAddr->pid, DbgPid, DbgSid );
  328.  
  329.      if( (SerialParallel() == SERIAL) && (SingleMultiple()==MULTIPLE) )
  330.      {
  331.       /***********************************************************************/
  332.       /* - For serial multiple process debugging:                            */
  333.       /***********************************************************************/
  334.       p = GetPidConnected();
  335.  
  336.       if( p )
  337.       {
  338.        /**********************************************************************/
  339.        /* - Preempt the current connection.                                  */
  340.        /**********************************************************************/
  341.  
  342.        TorF = TRUE;
  343.        if( p->pid == DbgGetProcessID() )
  344.         TorF = FALSE;
  345.  
  346.        SetConnectSema4( &p->ConnectSema4, TorF );
  347.  
  348.        p->PidFlags.ConnectYielded = TRUE;
  349.        p->Connect                 = DISCONNECTED;
  350.       }
  351.  
  352.       /***********************************************************************/
  353.       /* - Connect the new process.                                          */
  354.       /***********************************************************************/
  355.       pid        = pDataAddr->pid;
  356.       p          = GetPid( pid );
  357.       p->Connect = CONNECTED;
  358.  
  359.       /**********************************************************************/
  360.       /* - Wait for the connect sema4 to be created and put into the shared */
  361.       /*   heap structure.                                                  */
  362.       /**********************************************************************/
  363.       if( (SerialParallel() == SERIAL) && (SingleMultiple() == MULTIPLE) )
  364.       {
  365.        while( p->ConnectSema4 == 0 ) { DosSleep(200); }
  366.       }
  367.  
  368.       /**********************************************************************/
  369.       /* - Connect the probe of the new process.                            */
  370.       /* - Post the connect sema4 and let the new process start.            */
  371.       /**********************************************************************/
  372.       xConnectEsp( LsnHandle, pid );
  373.       PostConnectSema4( &p->ConnectSema4, TRUE );
  374.  
  375.       /**********************************************************************/
  376.       /* - Wait for the debugger to finish initializing.                    */
  377.       /**********************************************************************/
  378.       while( p->PidFlags.Initializing == TRUE) { DosSleep(200); }
  379.  
  380.       /***********************************************************************/
  381.       /* - Start the polling thread back up.                                 */
  382.       /***********************************************************************/
  383.       _beginthread( PollForMsgFromEsp, NULL, 0x8000, NULL );
  384.      }
  385.     }
  386.     break;
  387.  
  388. /*---------------------------------------------------------------------------*/
  389. /* All of the messages until the next dashed comment line are for serial     */
  390. /* connections only.                                                         */
  391. /*---------------------------------------------------------------------------*/
  392.  
  393.    case DBG_QMSG_CONNECT_ESP:
  394.     /************************************************************************/
  395.     /* - Serial message only.                                               */
  396.     /* - Kill the polling thread if running serial.  This will guarantee    */
  397.     /*   that no other messages will be serviced during ctrl-break          */
  398.     /*   processing.                                                        */
  399.     /* - Wait for the polling thread to die.                                */
  400.     /* - Grab the serial mutex.                                             */
  401.     /************************************************************************/
  402.     if( GetPollingThreadFlag() == RUNNING )
  403.     {
  404.      SetPollingThreadFlag( THREAD_TERM );
  405.      while( GetPollingThreadFlag() != NOT_RUNNING ){ DosSleep(100) ;}
  406.     }
  407.     RequestSerialMutex();
  408.  
  409.     /*************************************************************************/
  410.     /* - Serial channel message only.                                        */
  411.     /* - Disconnect the probe that is currently connected and connect the    */
  412.     /*   probe for the pid specified in the message.                         */
  413.     /*************************************************************************/
  414.     {
  415.      USHORT             YieldPid;
  416.      USHORT             GoToPid;
  417.      ALLPIDS           *pYield;
  418.      ALLPIDS           *pGoTo;
  419.  
  420.      YieldPid = (USHORT)pDataAddr->sid;
  421.      GoToPid  = pDataAddr->pid;
  422.  
  423.      /************************************************************************/
  424.      /* - Disconnect the current pid.                                        */
  425.      /************************************************************************/
  426.      if( YieldPid != 0 )
  427.      {
  428.       pYield          = GetPid( YieldPid );
  429.       pYield->Connect = DISCONNECTED;
  430.  
  431.       pYield->PidFlags.ConnectYielded = TRUE;
  432.      }
  433.  
  434.      /************************************************************************/
  435.      /* - Connect the new pid.                                               */
  436.      /************************************************************************/
  437.      pGoTo           = GetPid( GoToPid );
  438.      pGoTo->Connect  = CONNECTED;
  439.      pGoTo->PidFlags.ConnectYielded = FALSE;
  440.  
  441.      /************************************************************************/
  442.      /* - Connect the probe for the goto pid.                                */
  443.      /************************************************************************/
  444.      if( pDataAddr->DbgMsgFlags.InformEsp == TRUE )
  445.       xConnectEsp( LsnHandle, GoToPid );
  446.  
  447.      /************************************************************************/
  448.      /* - Set a flag to indicate whether or not the sema4 has to be opened   */
  449.      /*   before it is posted.                                               */
  450.      /* - Post the connect sema4 for this debugger.                          */
  451.      /************************************************************************/
  452.      TorF = TRUE;
  453.      if( GoToPid == DbgGetProcessID() )
  454.       TorF = FALSE;
  455.  
  456.      PostConnectSema4( &pGoTo->ConnectSema4, TorF ); /* do not move!!!           */
  457.  
  458.      ReleaseSerialMutex();
  459.      _beginthread( PollForMsgFromEsp, NULL, 0x8000, NULL );
  460.     }
  461.     break;
  462.  
  463.    case DBG_QMSG_DISCONNECT:
  464.     /*************************************************************************/
  465.     /* - One of the esp execution services is being executed and is          */
  466.     /*   giving up its connection.                                           */
  467.     /*************************************************************************/
  468.     p          = GetPid( pDataAddr->pid );
  469.     p->Connect = DISCONNECTED;
  470.     break;
  471.  
  472. /*---------------------------------------------------------------------------*/
  473.  
  474.    case DBG_QMSG_ERROR:
  475.    {
  476.     QUE_ERR_ELEMENT *pQueErrElement =  (QUE_ERR_ELEMENT *)pDataAddr;
  477.     char            *pErrorMsg;
  478.     char             RcMessage[32];
  479.  
  480.     rc        = pQueErrElement->rc;
  481.     pErrorMsg = pQueErrElement->ErrorMsg;
  482.  
  483.     DosSelectSession(0);
  484.  
  485.     sprintf( RcMessage, "Esp Error rc=%d", rc );
  486.  
  487.     ErrorPrintf( ERR_DBG_QUE_ERROR, 2, RcMessage, pErrorMsg );
  488.    }
  489.    break;
  490.  
  491.    case DBG_QMSG_KILL_LISTEN:
  492.     /*************************************************************************/
  493.     /* - Kill the listen thread or the polling threads.                      */
  494.     /*************************************************************************/
  495.     if( ListenThreadID )
  496.      xSendKillListen( LsnHandle );
  497.     break;
  498.  
  499.    case DBG_QMSG_PARENT_TERM:
  500.     /*************************************************************************/
  501.     /* - The parent probe is terminating.                                    */
  502.     /*************************************************************************/
  503.     for( p = GetAllpids(); p ; p = p->next )
  504.     {
  505.      if( p->pid != DbgGetProcessID() )
  506.      {
  507.       DBG_QUE_ELEMENT Qelement;
  508.  
  509.       Qelement.pid = p->DbgPid;
  510.  
  511.       SendMsgToDbgTermQue(DBG_TERMINATE, &Qelement, sizeof(Qelement) );
  512.      }
  513.     }
  514.     /*************************************************************************/
  515.     /* - There may not be any child dbgs, so set this flag so the parent     */
  516.     /*   can terminate.                                                      */
  517.     /*************************************************************************/
  518.     if(GetAllpids()->next == NULL)
  519.     {
  520.      AllDbgsAreDeadFlag = TRUE;
  521.     }
  522.     break;
  523.  
  524.    case DBG_QMSG_CHILD_TERM:
  525.     /*************************************************************************/
  526.     /* - A child probe has terminated.                                       */
  527.     /*************************************************************************/
  528.     RemovePid( pDataAddr->pid );
  529.  
  530.     /*************************************************************************/
  531.     /* - After the last probe has terminated, then report all probes dead.   */
  532.     /*************************************************************************/
  533.     if(GetAllpids()->next == NULL)
  534.     {
  535.      AllDbgsAreDeadFlag = TRUE;
  536.     }
  537.  
  538.     if( SerialParallel() == SERIAL )
  539.     {
  540.      DBG_QUE_ELEMENT Qelement;
  541.  
  542.      /************************************************************************/
  543.      /* - If the child is the currently connected debugger, then we          */
  544.      /*   we need to give the focus to another debugger. So,                 */
  545.      /*   give the focus to the parent debugger.                             */
  546.      /************************************************************************/
  547.      memset( &Qelement, 0, sizeof(Qelement) );
  548.      Qelement.pid = DbgGetProcessID();
  549.  
  550.      SendMsgToDbgQue( DBG_QMSG_SELECT_SESSION, &Qelement, sizeof(Qelement) );
  551.     }
  552.     break;
  553.  
  554.    case DBG_QMSG_QUE_TERM:
  555.     /*************************************************************************/
  556.     /* - Terminate and reset the queue for a possible restart.               */
  557.     /* - Close the queue to queue message channel.                           */
  558.     /* - Free the shared memory allocated for the pid structures.            */
  559.     /*************************************************************************/
  560.     DosCloseQueue(QueHandle);
  561.  
  562.     if( (SerialParallel() == PARALLEL) && LsnHandle )
  563.      ConnectClose( LsnHandle );
  564.  
  565.     if( SingleMultiple() == MULTIPLE )
  566.      FreeSharedHeap();
  567.  
  568.     QueHandle     = 0;
  569.     EndThread     = TRUE;
  570.     ReadQueReady  = 0;
  571.  
  572.     break;
  573.   }
  574.  
  575.   /***************************************************************************/
  576.   /* - Free the shared memory used for the message and initialize the        */
  577.   /*   data element pointer for the next message.                            */
  578.   /***************************************************************************/
  579.   if( pDataAddr )
  580.    DosFreeMem(pDataAddr);
  581.  
  582.   pDataAddr = NULL;
  583.  }
  584.  
  585.  /****************************************************************************/
  586.  /* - Come here after the DBG_QMSG_QUE_TERM message and end the que          */
  587.  /*   thread. We start all of this stuff back up on a restart.               */
  588.  /****************************************************************************/
  589.  if( IsVerbose() ) {printf("\nDbg Que Ended");fflush(0);}
  590.  _endthread();
  591. }                                       /* end ReadQ().                      */
  592.  
  593. /*****************************************************************************/
  594. /* SendMsgToDbgQue()                                                         */
  595. /*                                                                           */
  596. /* Description:                                                              */
  597. /*                                                                           */
  598. /*  Send DBG_QMSG_xxxxxx message to DBG queue. We pass through here just     */
  599. /*  to pick up the queue name.                                               */
  600. /*                                                                           */
  601. /* Parameters:                                                               */
  602. /*                                                                           */
  603. /*   Msg            DBG_QMSG_xxxxxx message.                                 */
  604. /*   PQueElement    -> to optional queue element( buffer ).                  */
  605. /*   QueElementLen  length of the queue element.                             */
  606. /*                                                                           */
  607. /* Return:                                                                   */
  608. /*                                                                           */
  609. /* Assumptions:                                                              */
  610. /*                                                                           */
  611. /*****************************************************************************/
  612. void SendMsgToDbgQue(ULONG Msg , void *pQueElement, ULONG QueElementLen)
  613. {
  614.  SendMsgToQue( DbgQueName, Msg, pQueElement, QueElementLen );
  615. }
  616.  
  617. /*****************************************************************************/
  618. /* ListenForMsgFromEsp()                                                     */
  619. /*                                                                           */
  620. /* Description:                                                              */
  621. /*                                                                           */
  622. /*   This function runs in its own thread and listens messages coming        */
  623. /*   to the queue from esp. This thread only exists when we're running       */
  624. /*   with a parallel connection.                                             */
  625. /*                                                                           */
  626. /* Parameters:                                                               */
  627. /*                                                                           */
  628. /*   handle   this is the handle to the connection.                          */
  629. /*                                                                           */
  630. /* Return:                                                                   */
  631. /*                                                                           */
  632. /* Assumptions:                                                              */
  633. /*                                                                           */
  634. /*****************************************************************************/
  635. void ListenForMsgFromEsp( void *handle )
  636. {
  637.  LHANDLE          LsnHandle = (LHANDLE)handle;
  638.  COMMAND          cmd;
  639.  DBG_QUE_ELEMENT  Qelement;
  640.  BOOL             EndThread;
  641.  
  642.  TXRX_NEW_PROCESS packet;
  643.  
  644.  if( IsVerbose() ) {printf("\nListen thread started");fflush(0);}
  645.  for( EndThread = FALSE ; EndThread == FALSE ; )
  646.  {
  647.   /***************************************************************************/
  648.   /* - Wait for a message coming from the probe.                             */
  649.   /***************************************************************************/
  650.   memset(&cmd,0,sizeof(cmd) );
  651.   RmtRecv(LsnHandle, (char*)&cmd, sizeof(cmd));
  652.  
  653.   if( IsVerbose() ) PrintCmdMessage( cmd.api ) ;
  654.   switch( cmd.api )
  655.   {
  656.    case NEW_PROCESS:
  657.  
  658.     /*************************************************************************/
  659.     /* - Handle new process notifications coming back from the remote probe. */
  660.     /*************************************************************************/
  661.     RmtRecv( LsnHandle, &packet, cmd.len );
  662.  
  663.     Qelement.pid  = packet.pid;
  664.     Qelement.type = packet.type;
  665.     strcpy(Qelement.FileSpec, packet.ProcessFileSpec);
  666.  
  667.     /*************************************************************************/
  668.     /* - Pass the message on to the que.                                     */
  669.     /*************************************************************************/
  670.     SendMsgToDbgQue( DBG_QMSG_NEW_PROCESS, &Qelement, sizeof(Qelement) );
  671.     break;
  672.  
  673.    case KILL_LISTEN_THREAD:
  674.    /**************************************************************************/
  675.    /* - This command will come from the esp queue when it gets a command     */
  676.    /*   to kill the listen thread during termination. The reason we do       */
  677.    /*   it this way is that DosKillThread() was causing a session hang       */
  678.    /*   when using MPTS on LS 4.0. So now, the debugger sends a command      */
  679.    /*   to the probe telling it to kill its listen thread. The probe sends   */
  680.    /*   a command back to the debugger telling it to also kill its listen    */
  681.    /*   thread and we end up raght 'chere.                                   */
  682.    /**************************************************************************/
  683.    EndThread = TRUE;
  684.    break;
  685.   }
  686.  }
  687.  if( IsVerbose() ) {printf("\nListen thread ended");fflush(0);}
  688.  _endthread();
  689. }
  690.  
  691. /*****************************************************************************/
  692. /* PollForMsgFromEsp()                                                       */
  693. /*                                                                           */
  694. /* Description:                                                              */
  695. /*                                                                           */
  696. /*   This function runs in its own thread and polls for messages from        */
  697. /*   esp. It's only applicable to serial multiple process configurations.    */
  698. /*                                                                           */
  699. /* Parameters:                                                               */
  700. /*                                                                           */
  701. /* Return:                                                                   */
  702. /*                                                                           */
  703. /* Assumptions:                                                              */
  704. /*                                                                           */
  705. /*   PollingThreadFlag states:                                               */
  706. /*                                                                           */
  707. /*    RUNNING        Thread is running.                                      */
  708. /*    NOT_RUNNING    Thread is not running.                                  */
  709. /*    THREAD_TERM    Transitional state from RUNNING to NOT_RUNNING.         */
  710. /*                                                                           */
  711. /*****************************************************************************/
  712. static int  PollingThreadFlag = NOT_RUNNING;
  713. void   SetPollingThreadFlag( int state ) { PollingThreadFlag = state;}
  714. int    GetPollingThreadFlag( void ) { return( PollingThreadFlag ); }
  715. void PollForMsgFromEsp( void *dummy )
  716. {
  717.  LHANDLE LsnHandle = GetComHandle();
  718.  COMMAND cmd;
  719.  
  720.  PollingThreadFlag = RUNNING;
  721.  
  722.  if( IsVerbose() ) {printf("\nPoll Thread Started");fflush(0);}
  723.  for( ; PollingThreadFlag == RUNNING ; )
  724.  {
  725.   DosSleep(200);
  726.  
  727.   RequestSerialMutex();
  728.  
  729.   /***************************************************************************/
  730.   /* - If this thread acquires the mutex after the termination flag has      */
  731.   /*   been set, then go ahead and terminate.                                */
  732.   /***************************************************************************/
  733.   memset(&cmd,0,sizeof(cmd) );
  734.  
  735.   cmd.api = SERIAL_POLL;
  736.   cmd.cmd = 0;
  737.   if( PollingThreadFlag == THREAD_TERM )
  738.   {;
  739.   }
  740.   else
  741.   {
  742.    if( IsVerbose() ) { printf("%c",'_'); fflush(0); }
  743.  
  744.    RmtSend( LsnHandle, &cmd, sizeof(cmd) );
  745.    RmtRecv( LsnHandle, &cmd, sizeof(cmd) );
  746.   }
  747.  
  748.   if( cmd.cmd != 0 )
  749.   {
  750.  
  751.    if( IsVerbose() ) PrintCmdMessage( (signed char)cmd.cmd ) ;
  752.  
  753.    switch( (signed char)cmd.cmd ) /* <---- Note this is the ".cmd" member  */
  754.    {
  755.     case NEW_PROCESS:
  756.     {
  757.      DBG_QUE_ELEMENT  Qelement;
  758.      TXRX_NEW_PROCESS packet;
  759.  
  760.      /************************************************************************/
  761.      /* - Handle new process notifications coming back from the remote probe.*/
  762.      /************************************************************************/
  763.      RmtRecv( LsnHandle, &packet, cmd.len );
  764.  
  765.      Qelement.pid = packet.pid;
  766.      strcpy(Qelement.FileSpec, packet.ProcessFileSpec);
  767.  
  768.      /*************************************************************************/
  769.      /* - Pass the message on to the que.                                     */
  770.      /*************************************************************************/
  771.      SendMsgToDbgQue( DBG_QMSG_NEW_PROCESS, &Qelement, sizeof(Qelement) );
  772.      PollingThreadFlag = THREAD_TERM;
  773.     }
  774.     break;
  775.  
  776.     case CONNECT_DBG:
  777.     {
  778.      USHORT   pid;
  779.      ALLPIDS *p;
  780.      BOOL     TorF;
  781.  
  782.      /************************************************************************/
  783.      /* - Handle connect requests coming from the remote probe.              */
  784.      /************************************************************************/
  785.      {
  786.       DBG_QUE_ELEMENT Qelement;
  787.  
  788.       /***********************************************************************/
  789.       /* - Receive the pid to be connected and connect it.                   */
  790.       /***********************************************************************/
  791.       RmtRecv( LsnHandle, &pid, cmd.len );
  792.  
  793.       p = GetPid( pid );
  794.  
  795.       p->Connect = CONNECTED;
  796.  
  797.       TorF = TRUE;
  798.       if( p->pid == DbgGetProcessID() )
  799.        TorF = FALSE;
  800.  
  801.       PostConnectSema4( &p->ConnectSema4, TorF );
  802.  
  803.       /***********************************************************************/
  804.       /* - Select the session of the debugger for this pid.                  */
  805.       /***********************************************************************/
  806.       Qelement.pid = pid;
  807.       SendMsgToDbgQue( DBG_QMSG_SELECT_SESSION, &Qelement, sizeof(Qelement) );
  808.  
  809.       /***********************************************************************/
  810.       /* - Tell the probe that the connection was made. A handshaking        */
  811.       /*   maneuver.                                                         */
  812.       /***********************************************************************/
  813.       memset(&cmd,0,sizeof(cmd) );
  814.       cmd.api = CONNECT_DBG;
  815.       RmtSend( LsnHandle, &cmd , sizeof(cmd) );
  816.      }
  817.     }
  818.     break;
  819.  
  820.     case CONNECT_NOTIFY:
  821.     {
  822.      ALLPIDS *p;
  823.      USHORT   pid;
  824.  
  825.      /************************************************************************/
  826.      /* - Receive the pid requesting the connection.                         */
  827.      /* - Turn on a flag to tell the debugger for this pid to pick up        */
  828.      /*   his notification.                                                  */
  829.      /************************************************************************/
  830.      RmtRecv( LsnHandle, &pid, sizeof(pid) );
  831.  
  832.      p = GetPid( pid );
  833.      p->PidFlags.RequestConnect = TRUE;
  834.     }
  835.     break;
  836.    }
  837.   }
  838.   ReleaseSerialMutex();
  839.  }
  840.  PollingThreadFlag = NOT_RUNNING;
  841.  if( IsVerbose() ) {printf("\nPoll Thread Ended");fflush(0);}
  842.  _endthread();
  843. }
  844.  
  845. /*****************************************************************************/
  846. /* StartDbgTermQue()                                                         */
  847. /*                                                                           */
  848. /* Description:                                                              */
  849. /*                                                                           */
  850. /*  Start up a que for terminating the debugger.                             */
  851. /*                                                                           */
  852. /* Parameters:                                                               */
  853. /*                                                                           */
  854. /* Return:                                                                   */
  855. /*                                                                           */
  856. /*  rc    System API return code.                                            */
  857. /*                                                                           */
  858. /* Assumptions:                                                              */
  859. /*                                                                           */
  860. /*****************************************************************************/
  861. static PSZ TermQueBaseName = "\\QUEUES\\TermQue";
  862.  
  863. APIRET StartDbgTermQue( void )
  864. {
  865.  APIRET   rc;
  866.  TIB     *pTib;
  867.  PIB     *pPib;
  868.  USHORT   ThisPid;
  869.  char     TermQueName[32];
  870.  char     PidString[12];
  871.  ALLPIDS *p;
  872.  
  873.  /****************************************************************************/
  874.  /* - Get the pid of this debugger and use it to define a unique name        */
  875.  /*   for this debugger's termination que.                                   */
  876.  /* - Stuff in the base que name.                                            */
  877.  /* - Concatenate the pid to make the name unique for the system.            */
  878.  /****************************************************************************/
  879.  DosGetInfoBlocks(&pTib, &pPib);
  880.  ThisPid = (USHORT)pPib->pib_ulpid;
  881.  
  882.  memset(TermQueName, 0, sizeof(TermQueName));
  883.  strcat(TermQueName, TermQueBaseName);
  884.  
  885.  memset(PidString, 0, sizeof(PidString));
  886.  sprintf( PidString, "%d", ThisPid );
  887.  strcat(TermQueName, PidString );
  888.  
  889.  /****************************************************************************/
  890.  /* - Now, start the que with a thread for this debugger.                    */
  891.  /****************************************************************************/
  892.  rc = StartQue(TermQueName, ReadDbgTermQue );
  893.  if(rc) return(rc);
  894.  
  895.  /****************************************************************************/
  896.  /* - Now, add the name of the queue to the shared memory structure for      */
  897.  /*   this debugger.                                                         */
  898.  /****************************************************************************/
  899.  p = GetDbgPid( ThisPid );
  900.  
  901.  DosSubAllocMem( GetShrMem(), (PPVOID)&(p->pTermQue), strlen(TermQueName) + 1 );
  902.  strcpy(p->pTermQue, TermQueName );
  903.  
  904.  return(0);
  905. }
  906.  
  907. /*****************************************************************************/
  908. /* ReadDbgTermQue()                                                          */
  909. /*                                                                           */
  910. /* Description:                                                              */
  911. /*                                                                           */
  912. /*   Read and handle termination message(s) coming to this debugger          */
  913. /*   from the parent debugger.                                               */
  914. /*                                                                           */
  915. /* Parameters:                                                               */
  916. /*                                                                           */
  917. /*   qHandle        -> to the queue handle. This is passed in by the         */
  918. /*                     StartQue() function when the queue is created.        */
  919. /*                                                                           */
  920. /* Return:                                                                   */
  921. /*                                                                           */
  922. /*  void                                                                     */
  923. /*                                                                           */
  924. /* Assumptions:                                                              */
  925. /*                                                                           */
  926. /*  This function runs in its own thread.                                    */
  927. /*                                                                           */
  928. /*****************************************************************************/
  929. void ReadDbgTermQue( void *qHandle)
  930. {
  931.  REQUESTDATA  Request;
  932.  ULONG        DataLen;
  933.  BYTE         ElePri;
  934.  BOOL         EndThread = FALSE;
  935.  LHANDLE      TermQueHandle;
  936.  
  937.  DBG_QUE_ELEMENT *pDataAddr=NULL;
  938.  
  939.  TermQueHandle = (LHANDLE)qHandle;
  940.  
  941.  /****************************************************************************/
  942.  /* - Start the que reading loop.                                            */
  943.  /****************************************************************************/
  944.  for(; EndThread == FALSE ;)
  945.  {
  946.   /***************************************************************************/
  947.   /* We're going to read an element from the term queue.  The queue is read  */
  948.   /* in FIFO order and we wait until there is a message to read.  We get an  */
  949.   /* element priority but we don't care about it.  Request.ulData contains   */
  950.   /* the message.                                                            */
  951.   /***************************************************************************/
  952.   DosReadQueue(TermQueHandle,
  953.                &Request,
  954.                &DataLen,
  955.                (PPVOID)&pDataAddr,
  956.                QUE_FIFO,
  957.                DCWW_WAIT,
  958.                &ElePri,
  959.                0L);
  960.  
  961.   /***************************************************************************/
  962.   /* - Handle the termination que message(s).                                */
  963.   /***************************************************************************/
  964.   switch( Request.ulData )
  965.   {
  966.    case DBG_TERMINATE:
  967.    {
  968.     USHORT          pid;
  969.     DBG_QUE_ELEMENT Qelement;
  970.  
  971.     pid = DbgGetProcessID();
  972.  
  973.     CloseConnectSema4();
  974.     ConnectClose( DEFAULT_HANDLE );
  975.  
  976.     memset( &Qelement, 0, sizeof(Qelement) );
  977.     Qelement.pid = pid;
  978.     SendMsgToDbgQue( DBG_QMSG_CHILD_TERM, &Qelement, sizeof(Qelement) );
  979.  
  980.     EndThread = TRUE;
  981.    }
  982.    break;
  983.  
  984.    case DBG_PROBE_TERM:
  985.    {
  986.     SetHaltCommunicationsFlag();
  987.    }
  988.    break;
  989.  
  990.    default:
  991.     break;
  992.   }
  993.  
  994.   /***************************************************************************/
  995.   /* - Free the shared memory used for the message and initialize the        */
  996.   /*   data element pointer for the next message.                            */
  997.   /***************************************************************************/
  998.   if( pDataAddr )
  999.    DosFreeMem(pDataAddr);
  1000.  
  1001.   pDataAddr = NULL;
  1002.  }
  1003.  
  1004.  /****************************************************************************/
  1005.  /* - Come here to end the que reading thread.                               */
  1006.  /****************************************************************************/
  1007.  if( IsVerbose() ) {printf("\nDebugger terminated");fflush(0);}
  1008.  exit(0);
  1009. }                                       /* end ReadQ().                      */
  1010.  
  1011. /*****************************************************************************/
  1012. /* SendMsgToDbgTermQue()                                                     */
  1013. /*                                                                           */
  1014. /* Description:                                                              */
  1015. /*                                                                           */
  1016. /*  Send TRM_QMSG_xxxxxx message to a child debugger.                        */
  1017. /*                                                                           */
  1018. /* Parameters:                                                               */
  1019. /*                                                                           */
  1020. /*   Msg            TRM_QMSG_xxxxxx message.                                 */
  1021. /*   PQueElement    -> to optional queue element( buffer ).                  */
  1022. /*   QueElementLen  length of the queue element.                             */
  1023. /*                                                                           */
  1024. /* Return:                                                                   */
  1025. /*                                                                           */
  1026. /* Assumptions:                                                              */
  1027. /*                                                                           */
  1028. /*   The process id receiving the queue message is passed in the queue       */
  1029. /*   element.                                                                */
  1030. /*                                                                           */
  1031. /*****************************************************************************/
  1032. void SendMsgToDbgTermQue(ULONG Msg , void *pQueElement, ULONG QueElementLen)
  1033. {
  1034.  USHORT   DbgPid;
  1035.  ALLPIDS *p;
  1036.  char    *pQueName;
  1037.  
  1038.  /****************************************************************************/
  1039.  /* - At this time, we are not actually sending anything in a queue element. */
  1040.  /*   However, we're allowing for future expansion.                          */
  1041.  /****************************************************************************/
  1042.  
  1043.  /****************************************************************************/
  1044.  /* - Get a ptr to the shared memory structure of the queue owner.           */
  1045.  /****************************************************************************/
  1046.  DbgPid = ((DBG_QUE_ELEMENT*)pQueElement)->pid;
  1047.  p      = GetDbgPid( DbgPid );
  1048.  if( p )
  1049.  {
  1050.   pQueName = p->pTermQue;
  1051.   SendMsgToQue( pQueName, Msg, pQueElement, QueElementLen );
  1052.  }
  1053. }
  1054.