void Shutdown(void) { int i; for (i = 0; i < nAgents; i++) { AgentInfo *ap = &agent[i]; if (!ap->status.connected) continue; if (ap->inFd != -1) { if (__pmSocketIPC(ap->inFd)) __pmCloseSocket(ap->inFd); else close(ap->inFd); } if (ap->outFd != -1) { if (__pmSocketIPC(ap->outFd)) __pmCloseSocket(ap->outFd); else close(ap->outFd); } if (ap->ipcType == AGENT_SOCKET && ap->ipc.socket.addrDomain == AF_UNIX) { /* remove the Unix domain socket */ unlink(ap->ipc.socket.name); } } if (HarvestAgents(SHUTDOWNWAIT) < 0) { /* terminate with prejudice any still remaining */ for (i = 0; i < nAgents; i++) { AgentInfo *ap = &agent[i]; if (ap->status.connected) { pid_t pid = ap->ipcType == AGENT_SOCKET ? ap->ipc.socket.agentPid : ap->ipc.pipe.agentPid; __pmProcessTerminate(pid, 1); } } } for (i = 0; i < nClients; i++) if (client[i].status.connected) __pmCloseSocket(client[i].fd); __pmServerCloseRequestPorts(); __pmSecureServerShutdown(); __pmNotifyErr(LOG_INFO, "pmcd Shutdown\n"); fflush(stderr); }
static void ShutdownAgent(AgentInfo *ap) { if (!ap->status.connected) return; if (ap->inFd != -1) { if (__pmSocketIPC(ap->inFd)) __pmCloseSocket(ap->inFd); else close(ap->inFd); } if (ap->outFd != -1) { if (__pmSocketIPC(ap->outFd)) __pmCloseSocket(ap->outFd); else close(ap->outFd); } if (ap->ipcType == AGENT_SOCKET && ap->ipc.socket.addrDomain == AF_UNIX) { /* remove the Unix domain socket */ unlink(ap->ipc.socket.name); } }
static int pduread(int fd, char *buf, int len, int part, int timeout) { int socketipc = __pmSocketIPC(fd); int status = 0; int have = 0; int onetrip = 1; struct timeval dead_hand; struct timeval now; if (timeout == -2 /*TIMEOUT_ASYNC*/) return -EOPNOTSUPP; /* * Handle short reads that may split a PDU ... * * The original logic here assumed that recv() would only split a * PDU at a word (__pmPDU) boundary ... with the introduction of * secure connections, SSL and possibly compression all lurking * below the socket covers, this is no longer a safe assumption. * * So, we keep nibbling at the input stream until we have all that * we have requested, or we timeout, or error. */ while (len) { struct timeval wait; #if defined(IS_MINGW) /* cannot select on a pipe on Win32 - yay! */ if (!__pmSocketIPC(fd)) { COMMTIMEOUTS cwait = { 0 }; if (timeout != TIMEOUT_NEVER) cwait.ReadTotalTimeoutConstant = timeout * 1000.0; else cwait.ReadTotalTimeoutConstant = def_timeout * 1000.0; SetCommTimeouts((HANDLE)_get_osfhandle(fd), &cwait); } else #endif /* * either never timeout (i.e. block forever), or timeout */ if (timeout != TIMEOUT_NEVER) { if (timeout > 0) { wait.tv_sec = timeout; wait.tv_usec = 0; } else wait = def_wait; if (onetrip) { /* * Need all parts of the PDU to be received by dead_hand * This enforces a low overall timeout for the whole PDU * (as opposed to just a timeout for individual calls to * recv). A more invasive alternative (better) approach * would see all I/O performed in the main event loop, * and I/O routines transformed to continuation-passing * style. */ gettimeofday(&dead_hand, NULL); dead_hand.tv_sec += wait.tv_sec; dead_hand.tv_usec += wait.tv_usec; while (dead_hand.tv_usec >= 1000000) { dead_hand.tv_usec -= 1000000; dead_hand.tv_sec++; } onetrip = 0; } status = __pmSocketReady(fd, &wait); if (status > 0) { gettimeofday(&now, NULL); if (now.tv_sec > dead_hand.tv_sec || (now.tv_sec == dead_hand.tv_sec && now.tv_usec > dead_hand.tv_usec)) status = 0; } if (status == 0) { if (__pmGetInternalState() != PM_STATE_APPL) { /* special for PMCD and friends * Note, on Linux select would return 'time remaining' * in timeout value, so report the expected timeout */ int tosec, tomsec; if ( timeout != TIMEOUT_NEVER && timeout > 0 ) { tosec = (int)timeout; tomsec = 0; } else { tosec = (int)def_wait.tv_sec; tomsec = 1000*(int)def_wait.tv_usec; } __pmNotifyErr(LOG_WARNING, "pduread: timeout (after %d.%03d " "sec) while attempting to read %d " "bytes out of %d in %s on fd=%d", tosec, tomsec, len - have, len, part == HEADER ? "HDR" : "BODY", fd); } return PM_ERR_TIMEOUT; } else if (status < 0) { char errmsg[PM_MAXERRMSGLEN]; __pmNotifyErr(LOG_ERR, "pduread: select() on fd=%d: %s", fd, netstrerror_r(errmsg, sizeof(errmsg))); setoserror(neterror()); return status; } } if (socketipc) { status = __pmRecv(fd, buf, len, 0); setoserror(neterror()); } else { status = read(fd, buf, len); } __pmOverrideLastFd(fd); if (status < 0) /* error */ return status; else if (status == 0) /* return what we have, or nothing */ break; have += status; buf += status; len -= status; #ifdef PCP_DEBUG if ((pmDebug & DBG_TRACE_PDU) && (pmDebug & DBG_TRACE_DESPERATE)) { fprintf(stderr, "pduread(%d, ...): have %d, last read %d, still need %d\n", fd, have, status, len); } #endif } return have; }
int __pmXmitPDU(int fd, __pmPDU *pdubuf) { int socketipc = __pmSocketIPC(fd); int off = 0; int len; __pmPDUHdr *php = (__pmPDUHdr *)pdubuf; __pmIgnoreSignalPIPE(); #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_PDU) { int j; char *p; int jend = PM_PDU_SIZE(php->len); char strbuf[20]; /* clear the padding bytes, lest they contain garbage */ p = (char *)pdubuf + php->len; while (p < (char *)pdubuf + jend*sizeof(__pmPDU)) *p++ = '~'; /* buffer end */ if (mypid == -1) mypid = (int)getpid(); fprintf(stderr, "[%d]pmXmitPDU: %s fd=%d len=%d", mypid, __pmPDUTypeStr_r(php->type, strbuf, sizeof(strbuf)), fd, php->len); for (j = 0; j < jend; j++) { if ((j % 8) == 0) fprintf(stderr, "\n%03d: ", j); fprintf(stderr, "%8x ", pdubuf[j]); } putc('\n', stderr); } #endif len = php->len; php->len = htonl(php->len); php->from = htonl(php->from); php->type = htonl(php->type); while (off < len) { char *p = (char *)pdubuf; int n; p += off; n = socketipc ? __pmSend(fd, p, len-off, 0) : write(fd, p, len-off); if (n < 0) break; off += n; } php->len = ntohl(php->len); php->from = ntohl(php->from); php->type = ntohl(php->type); if (off != len) { if (socketipc) { if (__pmSocketClosed()) return PM_ERR_IPC; return neterror() ? -neterror() : PM_ERR_IPC; } return oserror() ? -oserror() : PM_ERR_IPC; } __pmOverrideLastFd(fd); if (php->type >= PDU_START && php->type <= PDU_FINISH) __pmPDUCntOut[php->type-PDU_START]++; return off; }