/*
 * p4.c - code specific to initializing MPICH/P4 (mpich version 1 that is)
 *
 * $Id: p4.c 326 2006-01-24 21:35:26Z pw $
 *
 * Copyright (C) 2000-5 Pete Wyckoff <pw@osc.edu>
 *
 * Distributed under the GNU Public License Version 2 or later (See LICENSE)
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/time.h>
#include "mpiexec.h"

static int mport_fd;

/*
 * See corresponding code in mpid/ch_p4/p4/lib/p4_utils.c:
 * put_execer_port().
 */
int
prepare_p4_master_port(void)
{
    struct sockaddr_in sin;
    socklen_t len = sizeof(sin);

    mport_fd = socket(PF_INET, SOCK_DGRAM, 0);
    if (mport_fd < 0)
	error_errno("%s: socket", __func__);
    memset(&sin, 0, len);
    sin.sin_family = myaddr.sin_family;
    /*
     * Unfortunately we released mpich-1.2.4 with big master
     * assuming it will connect via loopback, restricting this use
     * only to cases where pbs node#0 hosts mpi task#0.  Until that is
     * fixed, leave sin_addr zeroed so that any interface can receive
     * the big master startup message.
     */
    /* sin.sin_addr = myaddr.sin_addr; */
    sin.sin_port = 0;
    if (bind(mport_fd, (struct sockaddr *)&sin, len) < 0)
	error_errno("%s: bind", __func__);
    if (getsockname(mport_fd, (struct sockaddr *) &sin, &len) < 0)
	error_errno("%s: getsockname", __func__);
    return ntohs(sin.sin_port);
}

int
read_p4_master_port(int *port)
{
    int cc, flags;
    int ret = 0;

    debug(1, "%s: waiting for port from master", __func__);
    *port = -1;

    /*
     * Poll for connection while checking if process died to avoid
     * hanging due to startup problems.
     */
    flags = fcntl(mport_fd, F_GETFL);
    if (flags < 0)
	error_errno("%s: get listen socket flags", __func__);
    if (fcntl(mport_fd, F_SETFL, flags | O_NONBLOCK) < 0)
	error_errno("%s: set listen socket nonblocking", __func__);

    for (;;) {
	cc = read(mport_fd, port, sizeof(*port));
	if (cc >= 0)
	    break;
	if (errno != EAGAIN)
	    error_errno("%s: read", __func__);

	/* check to see if any process died, and abort if so */
	if (poll_events_until_obit()) {
	    ret = 1;
	    goto out;
	}
	usleep(200000);
    }
    if (cc != sizeof(*port))
	error("%s: got %d bytes, expecting %d", __func__, cc,
	  (int) sizeof(*port));
  out:
    if (close(mport_fd) < 0)
	error_errno("%s: close", __func__);
    debug(1, "%s: got port %d", __func__, *port);
    return ret;
}



syntax highlighted by Code2HTML, v. 0.9.1