示例#1
0
/* 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" );
	}
    }
示例#2
0
/*@
  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;
}
示例#3
0
文件: pmiport.c 项目: NexMirror/MPICH
/*
 * 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;
}