/*----------------------------------------------------------------------+*/ 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); }
/* 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; }