Пример #1
0
/*----------------------------------------------------------------------+*/
protocol_request_ptr SPC_New_Protocol_Ptr (SPC_Channel_Ptr channel, 
					   XeChar req, 
					   int len)
/*----------------------------------------------------------------------+*/
{
  protocol_request_ptr prot;

  _DtSvcProcessLock();
  if(free_protocol_requests) {
    prot = free_protocol_requests;
    free_protocol_requests = free_protocol_requests->next;
  } else {
    prot = (protocol_request_ptr)XeMalloc(sizeof(protocol_request));
    prot->dataptr = SPC_New_Buffered_Data_Ptr();
  }
  SPC_Reset_Protocol_Ptr(prot, channel, req, len);
  _DtSvcProcessUnlock();
  return(prot);
}
Пример #2
0
/* This is the right way according to the Spec 1170 */
void SPC_Child_Terminated(int i)
/*----------------------------------------------------------------------+*/
{
  /* This catches signals for sub-process termination */
  int type, cause, status;
  pid_t wait_pid, pid;
  SPC_Channel_Ptr channel;
  protocol_request     req, *prot;
  buffered_data        data, *pdata;
  int length;
  int indx;
  int saved_errno = errno;

  prot  = (&req);
  pdata = (&data);

  prot->dataptr=pdata;

  wait_pid = -1;
  while(pid = waitpid(wait_pid, &status, WNOHANG)) {
    if((pid == -1 && errno == ECHILD) || pid == 0) {
      /* no more children.  Return */
      errno = saved_errno;
      return;
    }
    
    /* Okay, we got the process ID of a terminated child.  Find the
       channel associated with this PID. */
    channel=SPC_Find_PID(pid);
#ifdef DEBUG
    fprintf(stderr, (XeString)"got SIGCHLD, pid: %d, channel: %p\n", pid, channel);
#endif

    if(!channel) {
      continue;
    }

    _DtSvcProcessLock();
    /*
     * Look for this process in the pid list.  If found, mark it
     * as done.
     */
    if (SPC_pid_list != NULL) {
      for (indx=0; SPC_pid_list[indx] != NULL; indx++)
        if (SPC_pid_list[indx] == pid) {
	   SPC_pid_list[indx] = SPCD_DEAD_PROCESS;
	   break;
	}
    }
    _DtSvcProcessUnlock();

    /* We have the channel.  Mark it as being closed. */

    channel->status     = status;

    /* If we this channel is set up for synchronous termination,
       write the protocol request to record that this guy died.
       Otherwise, call the termination handler directly. */
    
    if(IS_SPCIO_SYNC_TERM(channel->IOMode)) {

      /* This code is basically what SPC_Write_Protocol_Request does.
	 It is replicated here because a call to SPC_W_P_R would have
	 to be re-enterant if we called it here, and SPC_W_P_R is not
	 re-enterant at this time. */
      
      SPC_Reset_Protocol_Ptr(prot, channel, APPLICATION_DIED, 0);
      pdata->len=WRITE_APPLICATION_DIED(pdata, status);
      length=WRITE_HEADER(pdata, channel->cid,
			  prot->request_type,
			  pdata->len,
			  0);
      pdata->data[length]=(XeChar)' ';
      length=pdata->len+REQUEST_HEADER_LENGTH;
      if(write(write_terminator->sid, pdata->data, length)==ERROR)
	SPC_Error(SPC_Internal_Error);
      pdata->offset=REQUEST_HEADER_LENGTH;
      print_protocol_request((XeString) (XeString)"  <-- INTERNAL APPLICATION_DIED", prot);
    }
    else {
      SPC_Change_State(channel, NULL, -1, 0);
      if(channel->Terminate_Handler) {
	XeSPCGetProcessStatus(channel, &type, &cause);
	(* channel->Terminate_Handler)
	  (channel, channel->pid, type, cause, channel->Terminate_Data);
      }
    }
    /* Loop around & get another PID */
  }
  errno = saved_errno;
}