/* On some systems (SGI IRIX 6), process exit sometimes kills all processes * in the process GROUP. This code attempts to fix that. * We DON'T do it if stdin (0) is connected to a terminal, because that * disconnects the process from the terminal. * ------------------------------------------------------------------------ */ void MPIE_CreateNewSession( void ) { #if defined(HAVE_SETSID) && defined(HAVE_ISATTY) && \ defined(USE_NEW_SESSION) && defined(HAVE_GETSID) #ifdef NEEDS_GETSID_DECL pid_t getsid(pid_t); #endif if (!isatty(0) && !isatty(1) && !isatty(2) && getsid(0) != getpid()) { pid_t rc; /* printf( "Creating a new session\n" ); */ /* printf( "Session id = %d and process id = %d\n", getsid(0), getpid() );*/ MPIE_SYSCALL(rc,setsid,()); if (rc < 0) { MPL_internal_sys_error_printf( "setsid", errno, "Could not create new process group\n" ); } }
/*@ MPIE_IOLoop - Handle all registered I/O Input Parameters: . timeoutSeconds - Seconds until this routine should return with a timeout error. If negative, no timeout. If 0, return immediatedly after a nonblocking check for I/O. Return Value: Returns zero on success. Returns 'IOLOOP_TIMEOUT' if the timeout is reached and 'IOLOOP_ERROR' on other errors. @*/ int MPIE_IOLoop(int timeoutSeconds) { int i, maxfd, fd, nfds, rc = 0, rc2; fd_set readfds, writefds; int (*handler) (int, int, void *); struct timeval tv; /* Loop on the fds, with the timeout */ TimeoutInit(timeoutSeconds); while (1) { tv.tv_sec = TimeoutGetRemaining(); tv.tv_usec = 0; /* Determine the active FDs */ FD_ZERO(&readfds); FD_ZERO(&writefds); /* maxfd is the maximum active fd */ maxfd = -1; for (i = 0; i <= maxFD; i++) { if (handlesByFD[i].handler) { fd = handlesByFD[i].fd; if (handlesByFD[i].rdwr & IO_READ) { FD_SET(fd, &readfds); maxfd = i; } if (handlesByFD[i].rdwr & IO_WRITE) { FD_SET(fd, &writefds); maxfd = i; } } } if (maxfd < 0) break; /* DBG_PRINTF(("Calling select with readfds = %x writefds = %x\n", */ /* *(int *)&readfds, *(int*)&writefds)); */ MPIE_SYSCALL(nfds, select, (maxfd + 1, &readfds, &writefds, 0, &tv)); if (nfds < 0 && (errno == EINTR || errno == 0)) { /* Continuing through EINTR */ /* We allow errno == 0 as a synonym for EINTR. We've seen this * on Solaris; in addition, we set errno to 0 after a failed * waitpid in the process routines, and if the OS isn't careful, * the value of errno may get ECHILD instead of EINTR when the * signal handler returns (we suspect Linux of this problem), * which is why we have the signal handler in process.c reset * errno to 0 (we may need to allow ECHILD here (!)) */ /* FIXME: an EINTR may also mean that a process has exited * (SIGCHILD). If all processes have exited, we may want to * exit */ DBG_PRINTF(("errno = EINTR in select\n")); continue; } if (nfds < 0) { /* Serious error */ MPL_internal_sys_error_printf("select", errno, 0); break; } if (nfds == 0) { /* Timeout from select */ DBG_PRINTF(("Timeout in select\n")); return IOLOOP_TIMEOUT; } /* nfds > 0 */ DBG_PRINTF(("Found some fds to process (n = %d)\n", nfds)); for (fd = 0; fd <= maxfd; fd++) { if (FD_ISSET(fd, &writefds)) { handler = handlesByFD[fd].handler; if (handler) { rc = (*handler) (fd, IO_WRITE, handlesByFD[fd].extra_data); } if (rc == 1) { /* EOF? */ MPIE_SYSCALL(rc2, close, (fd)); handlesByFD[fd].rdwr = 0; FD_CLR(fd, &writefds); } } if (FD_ISSET(fd, &readfds)) { handler = handlesByFD[fd].handler; if (handler) { rc = (*handler) (fd, IO_READ, handlesByFD[fd].extra_data); } if (rc == 1) { /* EOF? */ MPIE_SYSCALL(rc2, close, (fd)); handlesByFD[fd].rdwr = 0; FD_CLR(fd, &readfds); } } } } DBG_PRINTF(("Returning from IOLOOP handler\n")); return 0; }
/* * Input Parameters: * portLen - Number of characters in portString * Output Parameters: * fdout - An fd that is listening for connection attempts. * Use PMIServAcceptFromPort to process reads from this fd * portString - The name of a port that can be used to connect to * this process (using connect). */ int PMIServGetPort( int *fdout, char *portString, int portLen ) { int fd = -1; struct sockaddr_in sa; int optval = 1; int portnum; char *range_ptr; int low_port=0, high_port=0; /* Under cygwin we may want to use 1024 as a low port number */ /* a low and high port of zero allows the system to choose the port value */ /* Get the low and high portnumber range. zero may be used to allow the system to choose. There is a priority to these values, we keep going until we get one (and skip if none is found) */ range_ptr = getenv( "MPIEXEC_PORTRANGE" ); if (!range_ptr) { range_ptr = getenv( "MPIEXEC_PORT_RANGE" ); } if (!range_ptr) { range_ptr = getenv( "MPICH_PORT_RANGE" ); } if (range_ptr) { char *p; /* Look for n:m format */ p = range_ptr; while (*p && isspace(*p)) p++; while (*p && isdigit(*p)) low_port = 10 * low_port + (*p++ - '0'); if (*p == ':') { p++; while (*p && isdigit(*p)) high_port = 10 * high_port + (*p++ - '0'); } if (*p) { MPL_error_printf( "Invalid character %c in MPIEXEC_PORTRANGE\n", *p ); return -1; } } for (portnum=low_port; portnum<=high_port; portnum++) { memset( (void *)&sa, 0, sizeof(sa) ); sa.sin_family = AF_INET; sa.sin_port = htons( portnum ); sa.sin_addr.s_addr = INADDR_ANY; fd = socket( AF_INET, SOCK_STREAM, TCP ); if (fd < 0) { /* Failure; return immediately */ return fd; } if (setsockopt( fd, IPPROTO_TCP, TCP_NODELAY, (char *)&optval, sizeof(optval) )) { MPL_internal_sys_error_printf( "setsockopt", errno, 0 ); } if (bind( fd, (struct sockaddr *)&sa, sizeof(sa) ) < 0) { close( fd ); fd = -1; if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) { return -1; } } else { /* Success! We have a port. */ break; } } if (fd < 0) { /* We were unable to find a usable port */ return -1; } DBG_PRINTF( ("Listening on fd %d\n", fd) ); /* Listen is a non-blocking call that enables connections */ listen( fd, MAX_PENDING_CONN ); /* Make sure that this fd doesn't get sent to the children */ fcntl( fd, F_SETFD, FD_CLOEXEC ); *fdout = fd; if (portnum == 0) { socklen_t sinlen = sizeof(sa); /* We asked for *any* port, so we need to find which port we actually got */ getsockname( fd, (struct sockaddr *)&sa, &sinlen ); portnum = ntohs(sa.sin_port); } /* Create the port string */ { char hostname[MAX_HOST_NAME+1]; hostname[0] = 0; MPIE_GetMyHostName( hostname, sizeof(hostname) ); MPL_snprintf( portString, portLen, "%s:%d", hostname, portnum ); } return 0; }