From ef7e7548608b6e977bdd6d64cea71a46bc95addc Mon Sep 17 00:00:00 2001 From: David Ozog Date: Wed, 16 Feb 2022 16:47:24 -0500 Subject: [PATCH] pmi-simple: update to upstream (MPICH) state Requires some modifications for SOS: * include "config.h" instead of "mpichconf.h" * define MPI_MAX_PORT_NAME manually (w/out "mpi.h") * carry new pmi-simple reqs from MPICH (mpir_mem.h/mpl_sockaddr.h) * ignore strncasecmp/strnicmp requirement (not used in pmi-simple) --- pmi-simple/Makefile.am | 5 +- pmi-simple/mpir_mem.h | 243 ++++++ pmi-simple/mpl_sockaddr.c | 339 ++++++++ pmi-simple/mpl_sockaddr.h | 39 + pmi-simple/simple_pmi.c | 1534 ++++++++++++++++++------------------- 5 files changed, 1369 insertions(+), 791 deletions(-) create mode 100644 pmi-simple/mpir_mem.h create mode 100644 pmi-simple/mpl_sockaddr.c create mode 100644 pmi-simple/mpl_sockaddr.h diff --git a/pmi-simple/Makefile.am b/pmi-simple/Makefile.am index c5828e6f9..0d503b069 100644 --- a/pmi-simple/Makefile.am +++ b/pmi-simple/Makefile.am @@ -20,5 +20,8 @@ libpmi_simple_la_SOURCES = \ simple_pmiutil.c \ simple_pmiutil.h \ pmi.h \ - mpl.h + mpl.h \ + mpir_mem.h \ + mpl_sockaddr.c \ + mpl_sockaddr.h endif diff --git a/pmi-simple/mpir_mem.h b/pmi-simple/mpir_mem.h new file mode 100644 index 000000000..29edc09bc --- /dev/null +++ b/pmi-simple/mpir_mem.h @@ -0,0 +1,243 @@ +/* + * Copyright (C) by Argonne National Laboratory + * See COPYRIGHT in top-level directory + */ + +#ifndef MPIR_MEM_H_INCLUDED +#define MPIR_MEM_H_INCLUDED + +#include "config.h" + +/* Make sure that we have the definitions for the malloc routines and size_t */ +#include +#include +/* strdup is often declared in string.h, so if we plan to redefine strdup, + we need to include string first. That is done below, only in the + case where we redefine strdup */ + +#if defined(__cplusplus) +extern "C" { +#endif + +#include "mpl.h" + +/* Define attribute as empty if it has no definition */ +#ifndef ATTRIBUTE +#define ATTRIBUTE(a) +#endif + +#if defined (MPL_USE_DBG_LOGGING) + extern MPL_dbg_class MPIR_DBG_STRING; +#endif /* MPL_USE_DBG_LOGGING */ + +/* ------------------------------------------------------------------------- */ +/* mpir_mem.h */ +/* ------------------------------------------------------------------------- */ +/* Memory allocation */ +/* style: allow:malloc:2 sig:0 */ +/* style: allow:free:2 sig:0 */ +/* style: allow:strdup:2 sig:0 */ +/* style: allow:calloc:2 sig:0 */ +/* style: allow:realloc:1 sig:0 */ +/* style: allow:alloca:1 sig:0 */ +/* style: define:__strdup:1 sig:0 */ +/* style: define:strdup:1 sig:0 */ + /* style: allow:fprintf:5 sig:0 *//* For handle debugging ONLY */ +/* style: allow:snprintf:1 sig:0 */ + +/*D + Memory - Memory Management Routines + + Rules for memory management: + + MPICH explicitly prohibits the appearance of 'malloc', 'free', + 'calloc', 'realloc', or 'strdup' in any code implementing a device or + MPI call (of course, users may use any of these calls in their code). + Instead, you must use 'MPL_malloc' etc.; if these are defined + as 'malloc', that is allowed, but an explicit use of 'malloc' instead of + 'MPL_malloc' in the source code is not allowed. This restriction is + made to simplify the use of portable tools to test for memory leaks, + overwrites, and other consistency checks. + + Most memory should be allocated at the time that 'MPID_Init' is + called and released with 'MPID_Finalize' is called. If at all possible, + no other routine should fail because memory could not be allocated + (for example, because the user has allocated large arrays after 'MPI_Init'). + + The implementation of the MPI routines will strive to avoid memory allocation + as well; however, operations such as 'MPI_Type_index' that create a new + data type that reflects data that must be copied from an array of arbitrary + size will have to allocate memory (and can fail; note that there is an + MPI error class for out-of-memory). + + Question: + Do we want to have an aligned allocation routine? E.g., one that + aligns memory on a cache-line. + D*/ + +/* Define the string copy and duplication functions */ +/* ------------------------------------------------------------------------- */ + +#define MPIR_Memcpy(dst, src, len) \ + do { \ + CHECK_MEMCPY((dst),(src),(len)); \ + memcpy((dst), (src), (len)); \ + } while (0) + +#define MPIR_Memcpy_stream(dst, src, len) \ + do { \ + CHECK_MEMCPY((dst),(src),(len)); \ + MPL_Memcpy_stream((dst), (src), (len)); \ + } while (0) + +/* Memory allocation macros. See document. */ + +/* Standard macro for generating error codes. We set the error to be + * recoverable by default, but this can be changed. */ +#ifdef HAVE_ERROR_CHECKING +#define MPIR_CHKMEM_SETERR(rc_,nbytes_,name_) \ + rc_=MPIR_Err_create_code(MPI_SUCCESS, \ + MPIR_ERR_RECOVERABLE, __func__, __LINE__, \ + MPI_ERR_OTHER, "**nomem2", "**nomem2 %d %s", nbytes_, name_) +#else /* HAVE_ERROR_CHECKING */ +#define MPIR_CHKMEM_SETERR(rc_,nbytes_,name_) rc_=MPI_ERR_OTHER +#endif /* HAVE_ERROR_CHECKING */ + + /* CHKPMEM_REGISTER is used for memory allocated within another routine */ + +#define MPIR_CHKLMEM_DECL(n_) \ + void *(mpiu_chklmem_stk_[n_]) = { NULL }; \ + int mpiu_chklmem_stk_sp_=0; \ + MPIR_AssertDeclValue(const int mpiu_chklmem_stk_sz_,n_) + +#define MPIR_CHKLMEM_MALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,class_,stmt_) \ + { \ + pointer_ = (type_)MPL_malloc(nbytes_,class_); \ + if (pointer_) { \ + MPIR_Assert(mpiu_chklmem_stk_sp_ 0) { \ + MPIR_CHKMEM_SETERR(rc_,nbytes_,name_); \ + stmt_; \ + } \ + } +#define MPIR_CHKLMEM_FREEALL() \ + do { \ + while (mpiu_chklmem_stk_sp_ > 0) { \ + MPL_free(mpiu_chklmem_stk_[--mpiu_chklmem_stk_sp_]); \ + } \ + } while (0) + +#define MPIR_CHKLMEM_MALLOC(pointer_,type_,nbytes_,rc_,name_,class_) \ + MPIR_CHKLMEM_MALLOC_ORJUMP(pointer_,type_,nbytes_,rc_,name_,class_) +#define MPIR_CHKLMEM_MALLOC_ORJUMP(pointer_,type_,nbytes_,rc_,name_,class_) \ + MPIR_CHKLMEM_MALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,class_,goto fn_fail) + +/* Persistent memory that we may want to recover if something goes wrong */ +#define MPIR_CHKPMEM_DECL(n_) \ + void *(mpiu_chkpmem_stk_[n_]) = { NULL }; \ + int mpiu_chkpmem_stk_sp_=0; \ + MPIR_AssertDeclValue(const int mpiu_chkpmem_stk_sz_,n_) +#define MPIR_CHKPMEM_MALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,class_,stmt_) \ + { \ + pointer_ = (type_)MPL_malloc(nbytes_,class_); \ + if (pointer_) { \ + MPIR_Assert(mpiu_chkpmem_stk_sp_ 0) { \ + MPIR_CHKMEM_SETERR(rc_,nbytes_,name_); \ + stmt_; \ + } \ + } +#define MPIR_CHKPMEM_REGISTER(pointer_) \ + { \ + MPIR_Assert(mpiu_chkpmem_stk_sp_ 0) { \ + MPL_free(mpiu_chkpmem_stk_[--mpiu_chkpmem_stk_sp_]); \ + } \ + } +#define MPIR_CHKPMEM_COMMIT() \ + mpiu_chkpmem_stk_sp_ = 0 +#define MPIR_CHKPMEM_MALLOC(pointer_,type_,nbytes_,rc_,name_,class_) \ + MPIR_CHKPMEM_MALLOC_ORJUMP(pointer_,type_,nbytes_,rc_,name_,class_) +#define MPIR_CHKPMEM_MALLOC_ORJUMP(pointer_,type_,nbytes_,rc_,name_,class_) \ + MPIR_CHKPMEM_MALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,class_,goto fn_fail) + +/* now the CALLOC version for zeroed memory */ +#define MPIR_CHKPMEM_CALLOC(pointer_,type_,nbytes_,rc_,name_,class_) \ + MPIR_CHKPMEM_CALLOC_ORJUMP(pointer_,type_,nbytes_,rc_,name_,class_) +#define MPIR_CHKPMEM_CALLOC_ORJUMP(pointer_,type_,nbytes_,rc_,name_,class_) \ + MPIR_CHKPMEM_CALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,class_,goto fn_fail) +#define MPIR_CHKPMEM_CALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,class_,stmt_) \ + do { \ + pointer_ = (type_)MPL_calloc(1, (nbytes_), (class_)); \ + if (pointer_) { \ + MPIR_Assert(mpiu_chkpmem_stk_sp_ 0) { \ + MPIR_CHKMEM_SETERR(rc_,nbytes_,name_); \ + stmt_; \ + } \ + } while (0) + +/* A special version for routines that only allocate one item */ +#define MPIR_CHKPMEM_MALLOC1(pointer_,type_,nbytes_,rc_,name_,class_,stmt_) \ + { \ + pointer_ = (type_)MPL_malloc(nbytes_,class_); \ + if (!(pointer_) && (nbytes_ > 0)) { \ + MPIR_CHKMEM_SETERR(rc_,nbytes_,name_); \ + stmt_; \ + } \ + } + +/* Provides a easy way to use realloc safely and avoid the temptation to use + * realloc unsafely (direct ptr assignment). Zero-size reallocs returning NULL + * are handled and are not considered an error. */ +#define MPIR_REALLOC_ORJUMP(ptr_,size_,class_,rc_) \ + do { \ + void *realloc_tmp_ = MPL_realloc((ptr_), (size_), (class_)); \ + if (size_ != 0) \ + MPIR_ERR_CHKANDJUMP2(!realloc_tmp_,rc_,MPI_ERR_OTHER,"**nomem2","**nomem2 %d %s",(size_),MPL_QUOTE(ptr_)); \ + (ptr_) = realloc_tmp_; \ + } while (0) + +/* Evaluates to a boolean expression, true if the given byte ranges overlap, + * false otherwise. That is, true iff [a_,a_+a_len_) overlaps with [b_,b_+b_len_) */ +#define MPIR_MEM_RANGES_OVERLAP(a_,a_len_,b_,b_len_) \ + (((char *)(a_) >= (char *)(b_) && ((char *)(a_) < ((char *)(b_) + (b_len_)))) || \ + ((char *)(b_) >= (char *)(a_) && ((char *)(b_) < ((char *)(a_) + (a_len_))))) +#if (!defined(NDEBUG) && defined(HAVE_ERROR_CHECKING)) + +/* May be used to perform sanity and range checking on memcpy and mempcy-like + function calls. This macro will bail out much like an MPIR_Assert if any of + the checks fail. */ +#define CHECK_MEMCPY(dst_,src_,len_) \ + do { \ + if (len_ != 0) { \ + MPL_VG_CHECK_MEM_IS_ADDRESSABLE((dst_),(len_)); \ + MPL_VG_CHECK_MEM_IS_ADDRESSABLE((src_),(len_)); \ + if (MPIR_MEM_RANGES_OVERLAP((dst_),(len_),(src_),(len_))) { \ + MPIR_Assert_fmt_msg(FALSE,("memcpy argument memory ranges overlap, dst_=%p src_=%p len_=%ld\n", \ + (dst_), (src_), (long)(len_))); \ + } \ + } \ + } while (0) +#else +#define CHECK_MEMCPY(dst_,src_,len_) do {} while (0) +#endif + +/* valgrind macros are now provided by MPL (via mpl.h included in mpiimpl.h) */ + +/* ------------------------------------------------------------------------- */ +/* end of mpir_mem.h */ +/* ------------------------------------------------------------------------- */ + +#if defined(__cplusplus) +} +#endif +#endif /* MPIR_MEM_H_INCLUDED */ diff --git a/pmi-simple/mpl_sockaddr.c b/pmi-simple/mpl_sockaddr.c new file mode 100644 index 000000000..788f9d224 --- /dev/null +++ b/pmi-simple/mpl_sockaddr.c @@ -0,0 +1,339 @@ +/* + * Copyright (C) by Argonne National Laboratory + * See COPYRIGHT in top-level directory + */ + +/** Rationale: + * MPL wrap for handling IPv4 and IPv6. + * + * Applications: pm, pmi, ch3. + * ch4 supports tcp sockets indirectly through ucx and ofi. + */ + +/** Design considerations: + * Either IPv4 or IPv6, globally set as default or with command line option, to + * simplify logic. + * TCP only, no UDP or unix domain sockets. + * + * Application use struct sockaddr_storage (typedefed to MPL_sockaddr_t) exclusively. + * MPL_get_sockaddr for hostname + * MPL_get_sockaddr_iface for network interface + * MPL_get_sockaddr_direct for listening socket on ANY or LOOPBACK + * + * Simplified MPL_connect and MPL_listen interface. + * Both have a port parameter. + * MPL_listen combines bind with listen. + */ + +/** Portability: + * struct sockaddr_storage: + * In case this struct is not available (in sys/socket.h), it can be + * circumvented by declare following (in mpl_sockaddr.h): + * struct sockaddr_storage { + * unsigend short ss_family; + * char padding[126]; + * }; + * Since we use typedef MPL_sockaddr_t, there is no need for code change. + * Only the ss_family field is directly accessed. All the other fields are + * always accessed by casting to either struct sockaddr_in or struct + * sockaddr_in6. + * + * The implementation uses getaddrinfo and getifaddrs. The former, as with + * sockaddr_storage and sockaddr_in6, are documented in RFC 2553, 1999, and are + * expected to be supported on most supported platforms. getifaddrs is not in + * POSIX.1, but it is present on Linux since glibc 2.3.3, and available on BSD + * systems even earlier. + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mpl_sockaddr.h" + +static int is_localhost(struct sockaddr *p_addr); + +static int af_type = AF_INET; +static int _use_loopback = 0; +static int _max_conn = SOMAXCONN; + +void MPL_sockaddr_set_aftype(int type) +{ + af_type = type; +} + +int MPL_get_sockaddr(const char *s_hostname, MPL_sockaddr_t * p_addr) +{ + struct addrinfo ai_hint; + struct addrinfo *ai_list; + int ret; + +#ifdef __APPLE__ + /* Macos adds .local to hostname when network is unavailable or limited. + * This will result in long timeout in getaddrinfo below. + * Bypass it by resetting the hostname to "localhost" + */ + int n = strlen(s_hostname); + if (n > 6 && strcmp(s_hostname + n - 6, ".local") == 0) { + s_hostname = "localhost"; + } +#endif + + /* NOTE: there is report that getaddrinfo implementations will call kernel + * even when s_hostname is entirely numerical string and it may cause + * problems when host is configured with thousands of ip addresses. + */ + /* TODO: detect the cases when s_hostname is entirely numerical string and + * call inet_pton directly (-- do this on first bug report). + */ + memset(p_addr, 0, sizeof(*p_addr)); + memset(&ai_hint, 0, sizeof(ai_hint)); + ai_hint.ai_family = af_type; + ai_hint.ai_socktype = SOCK_STREAM; + ai_hint.ai_protocol = IPPROTO_TCP; + ret = getaddrinfo(s_hostname, NULL, &ai_hint, &ai_list); + if (ret) { + return ret; + } + if (af_type == AF_INET) { + memcpy(p_addr, ai_list->ai_addr, sizeof(struct sockaddr_in)); + } else if (af_type == AF_INET6) { + memcpy(p_addr, ai_list->ai_addr, sizeof(struct sockaddr_in6)); + } else { + assert(0); + } + freeaddrinfo(ai_list); + return 0; +} + +int MPL_get_sockaddr_direct(int type, MPL_sockaddr_t * p_addr) +{ + memset(p_addr, 0, sizeof(*p_addr)); + assert(type == MPL_SOCKADDR_ANY || type == MPL_SOCKADDR_LOOPBACK); + if (af_type == AF_INET) { + struct sockaddr_in *p_addr4 = (struct sockaddr_in *) p_addr; + + p_addr4->sin_family = AF_INET; + if (type == MPL_SOCKADDR_LOOPBACK) { + p_addr4->sin_addr.s_addr = htonl(0x7f000001); + } else { + p_addr4->sin_addr.s_addr = htonl(INADDR_ANY); + } + return 0; + } else if (af_type == AF_INET6) { + struct sockaddr_in6 *p_addr6 = (struct sockaddr_in6 *) p_addr; + + p_addr6->sin6_family = AF_INET6; + if (type == MPL_SOCKADDR_LOOPBACK) { + p_addr6->sin6_addr = in6addr_loopback; + } else { + p_addr6->sin6_addr = in6addr_any; + } + return 0; + } else { + assert(0); + return -1; + } +} + +int MPL_get_sockaddr_iface(const char *s_iface, MPL_sockaddr_t * p_addr) +{ + struct ifaddrs *ifaddr; + int ret; + struct ifaddrs *ifa; + int found = 0; + + memset(p_addr, 0, sizeof(*p_addr)); + ret = getifaddrs(&ifaddr); + if (ret) { + return ret; + } + ifa = ifaddr; + while (ifa) { + if (s_iface && ifa->ifa_name && strcmp(s_iface, ifa->ifa_name) != 0) { + ifa = ifa->ifa_next; + continue; + } + if (ifa->ifa_addr && ifa->ifa_addr->sa_family == af_type) { + found++; + if (af_type == AF_INET) { + memcpy(p_addr, ifa->ifa_addr, sizeof(struct sockaddr_in)); + } else if (af_type == AF_INET6) { + memcpy(p_addr, ifa->ifa_addr, sizeof(struct sockaddr_in6)); + } + if (!is_localhost((struct sockaddr *) ifa->ifa_addr)) { + break; + } + } + ifa = ifa->ifa_next; + } + freeifaddrs(ifaddr); + if (!found) { + return -1; + } else { + return 0; + } +} + +int MPL_socket(void) +{ + return socket(af_type, SOCK_STREAM, IPPROTO_TCP); +} + +int MPL_connect(int sock_fd, MPL_sockaddr_t * p_addr, unsigned short port) +{ + if (af_type == AF_INET) { + ((struct sockaddr_in *) p_addr)->sin_port = htons(port); + return connect(sock_fd, (const struct sockaddr *) p_addr, sizeof(struct sockaddr_in)); + } else if (af_type == AF_INET6) { + ((struct sockaddr_in6 *) p_addr)->sin6_port = htons(port); + return connect(sock_fd, (const struct sockaddr *) p_addr, sizeof(struct sockaddr_in6)); + } else { + return -1; + } +} + +void MPL_set_listen_attr(int use_loopback, int max_conn) +{ + _use_loopback = use_loopback; + _max_conn = max_conn; +} + +int MPL_listen(int sock_fd, unsigned short port) +{ + MPL_sockaddr_t addr; + int ret = 0; + + if (_use_loopback) { + MPL_get_sockaddr_direct(MPL_SOCKADDR_LOOPBACK, &addr); + } else { + MPL_get_sockaddr_direct(MPL_SOCKADDR_ANY, &addr); + } + if (af_type == AF_INET) { + ((struct sockaddr_in *) &addr)->sin_port = htons(port); + ret = bind(sock_fd, (const struct sockaddr *) &addr, sizeof(struct sockaddr_in)); + } else if (af_type == AF_INET6) { + ((struct sockaddr_in6 *) &addr)->sin6_port = htons(port); + ret = bind(sock_fd, (const struct sockaddr *) &addr, sizeof(struct sockaddr_in6)); + } else { + assert(0); + } + if (ret) { + return ret; + } + return listen(sock_fd, _max_conn); +} + +int MPL_listen_anyport(int sock_fd, unsigned short *p_port) +{ + MPL_sockaddr_t addr; + int ret = 0; + + if (_use_loopback) { + MPL_get_sockaddr_direct(MPL_SOCKADDR_LOOPBACK, &addr); + } else { + MPL_get_sockaddr_direct(MPL_SOCKADDR_ANY, &addr); + } + if (af_type == AF_INET) { + ((struct sockaddr_in *) &addr)->sin_port = 0; + ret = bind(sock_fd, (const struct sockaddr *) &addr, sizeof(struct sockaddr_in)); + } else if (af_type == AF_INET6) { + ((struct sockaddr_in6 *) &addr)->sin6_port = 0; + ret = bind(sock_fd, (const struct sockaddr *) &addr, sizeof(struct sockaddr_in6)); + } else { + assert(0); + } + if (ret) { + return ret; + } + unsigned int n = sizeof(addr); + ret = getsockname(sock_fd, (struct sockaddr *) &addr, &n); + if (ret) { + return ret; + } + if (af_type == AF_INET) { + *p_port = ntohs(((struct sockaddr_in *) &addr)->sin_port); + } else if (af_type == AF_INET6) { + *p_port = ntohs(((struct sockaddr_in6 *) &addr)->sin6_port); + } + return listen(sock_fd, _max_conn); +} + +int MPL_listen_portrange(int sock_fd, unsigned short *p_port, int low_port, int high_port) +{ + MPL_sockaddr_t addr; + int i; + int ret; + + if (_use_loopback) { + MPL_get_sockaddr_direct(MPL_SOCKADDR_LOOPBACK, &addr); + } else { + MPL_get_sockaddr_direct(MPL_SOCKADDR_ANY, &addr); + } + for (i = low_port; i <= high_port; i++) { + ret = MPL_listen(sock_fd, i); + if (ret == 0) { + *p_port = i; + break; + } else if (errno == EADDRINUSE) { + continue; + } else { + return -1; + } + } + if (i > high_port) { + return -2; + } + return listen(sock_fd, _max_conn); +} + +int MPL_sockaddr_to_str(MPL_sockaddr_t * p_addr, char *str, int maxlen) +{ + unsigned char *p; + + /* TODO: consider inet_ntop */ + if (p_addr->ss_family == AF_INET) { + p = (void *) &((struct sockaddr_in *) p_addr)->sin_addr; + snprintf(str, maxlen, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + } else if (p_addr->ss_family == AF_INET6) { + p = (void *) &((struct sockaddr_in6 *) p_addr)->sin6_addr; + snprintf(str, maxlen, + "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], + p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]); + } + return 0; +} + +int MPL_sockaddr_port(MPL_sockaddr_t * p_addr) +{ + if (p_addr->ss_family == AF_INET) { + return ntohs(((struct sockaddr_in *) p_addr)->sin_port); + } else if (p_addr->ss_family == AF_INET6) { + return ntohs(((struct sockaddr_in6 *) p_addr)->sin6_port); + } + return 0; +} + +int is_localhost(struct sockaddr *p_addr) +{ + char *p; + + if (p_addr->sa_family == AF_INET) { + p = (void *) &((struct sockaddr_in *) p_addr)->sin_addr; + return strncmp(p, "\x7f\x00\x00\x01", 4) == 0; + } else if (p_addr->sa_family == AF_INET6) { + p = (void *) &((struct sockaddr_in6 *) p_addr)->sin6_addr; + return strncmp(p, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01", 16) == 0 || + strncmp(p, "\xfe\x80\0\0\0\0\0\0\0\0\0\0\0\0\0\x01", 16) == 0; + } else { + return 0; + } +} diff --git a/pmi-simple/mpl_sockaddr.h b/pmi-simple/mpl_sockaddr.h new file mode 100644 index 000000000..636b2b101 --- /dev/null +++ b/pmi-simple/mpl_sockaddr.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) by Argonne National Laboratory + * See COPYRIGHT in top-level directory + */ + +#ifndef MPL_SOCKADDR_H_INCLUDED +#define MPL_SOCKADDR_H_INCLUDED + +#include + +#define MPL_SOCKADDR_ANY 0 +#define MPL_SOCKADDR_LOOPBACK 1 + +/* modifies the default behavior of MPL_Listen + * a - whether listen on loopback (default: listen on all interfaces) + * b - maximum simultaneous connection (default: SOMAXCONN) + */ +#define MPL_LISTEN_PUSH(a,b) MPL_set_listen_attr(a, b) +#define MPL_LISTEN_POP MPL_set_listen_attr(0, SOMAXCONN) + +typedef struct sockaddr_storage MPL_sockaddr_t; + +/* The following functions when return an int, it returns 0 on success, + * non-zero indicates error. It is consistent with posix socket functions. + */ +void MPL_sockaddr_set_aftype(int type); +int MPL_get_sockaddr(const char *s_hostname, MPL_sockaddr_t * p_addr); +int MPL_get_sockaddr_direct(int type, MPL_sockaddr_t * p_addr); +int MPL_get_sockaddr_iface(const char *s_iface, MPL_sockaddr_t * p_addr); +int MPL_socket(void); +int MPL_connect(int socket, MPL_sockaddr_t * p_addr, unsigned short port); +void MPL_set_listen_attr(int use_loopback, int max_conn); +int MPL_listen(int socket, unsigned short port); +int MPL_listen_anyport(int socket, unsigned short *p_port); +int MPL_listen_portrange(int socket, unsigned short *p_port, int low_port, int high_port); +int MPL_sockaddr_to_str(MPL_sockaddr_t * p_addr, char *str, int maxlen); +int MPL_sockaddr_port(MPL_sockaddr_t * p_addr); + +#endif /* MPL_SOCKADDR_H_INCLUDED */ diff --git a/pmi-simple/simple_pmi.c b/pmi-simple/simple_pmi.c index 2e318647e..148502ddd 100644 --- a/pmi-simple/simple_pmi.c +++ b/pmi-simple/simple_pmi.c @@ -1,19 +1,18 @@ -/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ -/* - * (C) 2001 by Argonne National Laboratory. - * See COPYRIGHT in top-level directory. +/* + * Copyright (C) by Argonne National Laboratory + * See COPYRIGHT in top-level directory */ /*********************** PMI implementation ********************************/ /* * This file implements the client-side of the PMI interface. * - * Note that the PMI client code must not print error messages (except + * Note that the PMI client code must not print error messages (except * when an abort is required) because MPI error handling is based on - * reporting error codes to which messages are attached. + * reporting error codes to which messages are attached. * * In v2, we should require a PMI client interface to use MPI error codes - * to provide better integration with MPICH. + * to provide better integration with MPICH. */ /***************************************************************************/ @@ -45,9 +44,10 @@ #include #endif -#include "mpl.h" /* Get ATTRIBUTE, some base functions */ +#include "mpl.h" /* Get ATTRIBUTE, some base functions */ /* mpimem includes the definitions for MPL_malloc and MPL_free */ -//#include "mpir_mem.h" +#include "mpir_mem.h" +#include "mpl_sockaddr.h" /* Temporary debug definitions */ /* #define DBG_PRINTF(args) printf args ; fflush(stdout) */ @@ -55,9 +55,9 @@ #include "pmi.h" #include "simple_pmiutil.h" -//#include "mpi.h" /* to get MPI_MAX_PORT_NAME */ +#define MPI_MAX_PORT_NAME 256 -/* +/* These are global variable used *ONLY* in this file, and are hence declared static. */ @@ -70,32 +70,33 @@ static int PMI_rank = 0; /* Set PMI_initialized to 1 for singleton init but no process manager to help. Initialized to 2 for normal initialization. Initialized to values higher than 2 when singleton_init by a process manager. - All values higher than 1 invlove a PM in some way. + All values higher than 1 involve a PM in some way. */ -typedef enum { PMI_UNINITIALIZED = 0, - SINGLETON_INIT_BUT_NO_PM = 1, - NORMAL_INIT_WITH_PM, - SINGLETON_INIT_WITH_PM } PMIState; +typedef enum { PMI_UNINITIALIZED = 0, + SINGLETON_INIT_BUT_NO_PM = 1, + NORMAL_INIT_WITH_PM, + SINGLETON_INIT_WITH_PM +} PMIState; static PMIState PMI_initialized = PMI_UNINITIALIZED; -/* ALL GLOBAL VARIABLES MUST BE INITIALIZED TO AVOID POLLUTING THE +/* ALL GLOBAL VARIABLES MUST BE INITIALIZED TO AVOID POLLUTING THE LIBRARY WITH COMMON SYMBOLS */ static int PMI_kvsname_max = 0; static int PMI_keylen_max = 0; static int PMI_vallen_max = 0; static int PMI_debug = 0; -static int PMI_debug_init = 0; /* Set this to true to debug the init - handshakes */ +static int PMI_debug_init = 0; /* Set this to true to debug the init + * handshakes */ static int PMI_spawned = 0; /* Function prototypes for internal routines */ -static int PMII_getmaxes( int *kvsname_max, int *keylen_max, int *vallen_max ); -static int PMII_Set_from_port( int, int ); -static int PMII_Connect_to_pm( char *, int ); +static int PMII_getmaxes(int *kvsname_max, int *keylen_max, int *vallen_max); +static int PMII_Set_from_port(int, int); +static int PMII_Connect_to_pm(char *, int); -static int GetResponse( const char [], const char [], int ); -static int getPMIFD( int * ); +static int GetResponse(const char[], const char[], int); +static int getPMIFD(int *); #ifdef USE_PMI_PORT static int PMII_singinit(void); @@ -110,211 +111,220 @@ static char singinit_kvsname[256]; /******************************** Group functions *************************/ -int PMI_Init( int *spawned ) +int PMI_Init(int *spawned) { char *p; int notset = 1; int rc; - + PMI_initialized = PMI_UNINITIALIZED; - + /* FIXME: Why is setvbuf commented out? */ /* FIXME: What if the output should be fully buffered (directed to file)? - unbuffered (user explicitly set?) */ + * unbuffered (user explicitly set?) */ /* setvbuf(stdout,0,_IONBF,0); */ - setbuf(stdout,NULL); - /* PMIU_printf( 1, "PMI_INIT\n" ); */ + setbuf(stdout, NULL); + /* PMIU_printf(1, "PMI_INIT\n"); */ /* Get the value of PMI_DEBUG from the environment if possible, since - we may have set it to help debug the setup process */ - p = getenv( "PMI_DEBUG" ); - if (p) PMI_debug = atoi( p ); + * we may have set it to help debug the setup process */ + p = getenv("PMI_DEBUG"); + if (p) + PMI_debug = atoi(p); /* Get the fd for PMI commands; if none, we're a singleton */ rc = getPMIFD(¬set); if (rc) { - return rc; + return rc; } - if ( PMI_fd == -1 ) { - /* Singleton init: Process not started with mpiexec, - so set size to 1, rank to 0 */ - PMI_size = 1; - PMI_rank = 0; - *spawned = 0; - - PMI_initialized = SINGLETON_INIT_BUT_NO_PM; - /* 256 is picked as the minimum allowed length by the PMI servers */ - PMI_kvsname_max = 256; - PMI_keylen_max = 256; - PMI_vallen_max = 256; - - return PMI_SUCCESS; + if (PMI_fd == -1) { + /* Singleton init: Process not started with mpiexec, + * so set size to 1, rank to 0 */ + PMI_size = 1; + PMI_rank = 0; + *spawned = 0; + + PMI_initialized = SINGLETON_INIT_BUT_NO_PM; + /* 256 is picked as the minimum allowed length by the PMI servers */ + PMI_kvsname_max = 256; + PMI_keylen_max = 256; + PMI_vallen_max = 256; + + return PMI_SUCCESS; } /* If size, rank, and debug are not set from a communication port, - use the environment */ + * use the environment */ if (notset) { - if ( ( p = getenv( "PMI_SIZE" ) ) ) - PMI_size = atoi( p ); - else - PMI_size = 1; - - if ( ( p = getenv( "PMI_RANK" ) ) ) { - PMI_rank = atoi( p ); - /* Let the util routine know the rank of this process for - any messages (usually debugging or error) */ - PMIU_Set_rank( PMI_rank ); - } - else - PMI_rank = 0; - - if ( ( p = getenv( "PMI_DEBUG" ) ) ) - PMI_debug = atoi( p ); - else - PMI_debug = 0; - - /* Leave unchanged otherwise, which indicates that no value - was set */ + if ((p = getenv("PMI_SIZE"))) + PMI_size = atoi(p); + else + PMI_size = 1; + + if ((p = getenv("PMI_RANK"))) { + PMI_rank = atoi(p); + /* Let the util routine know the rank of this process for + * any messages (usually debugging or error) */ + PMIU_Set_rank(PMI_rank); + } else + PMI_rank = 0; + + if ((p = getenv("PMI_DEBUG"))) + PMI_debug = atoi(p); + else + PMI_debug = 0; + + /* Leave unchanged otherwise, which indicates that no value + * was set */ } /* FIXME: Why does this depend on their being a port??? */ /* FIXME: What is this for? */ #ifdef USE_PMI_PORT - if ( ( p = getenv( "PMI_TOTALVIEW" ) ) ) - PMI_totalview = atoi( p ); - if ( PMI_totalview ) { - char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE]; - /* FIXME: This should use a cmd/response rather than a expecting the - server to set a value in this and only this case */ - /* FIXME: And it most ceratainly should not happen *before* the - initialization handshake */ - PMIU_readline( PMI_fd, buf, PMIU_MAXLINE ); - PMIU_parse_keyvals( buf ); - PMIU_getval( "cmd", cmd, PMIU_MAXLINE ); - if ( strncmp( cmd, "tv_ready", PMIU_MAXLINE ) != 0 ) { - PMIU_printf( 1, "expecting cmd=tv_ready, got %s\n", buf ); - return PMI_FAIL; - } + if ((p = getenv("PMI_TOTALVIEW"))) + PMI_totalview = atoi(p); + if (PMI_totalview) { + char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE]; + /* FIXME: This should use a cmd/response rather than a expecting the + * server to set a value in this and only this case */ + /* FIXME: And it most ceratainly should not happen *before* the + * initialization handshake */ + PMIU_readline(PMI_fd, buf, PMIU_MAXLINE); + PMIU_parse_keyvals(buf); + PMIU_getval("cmd", cmd, PMIU_MAXLINE); + if (strncmp(cmd, "tv_ready", PMIU_MAXLINE) != 0) { + PMIU_printf(1, "expecting cmd=tv_ready, got %s\n", buf); + return PMI_FAIL; + } } #endif - PMII_getmaxes( &PMI_kvsname_max, &PMI_keylen_max, &PMI_vallen_max ); + PMII_getmaxes(&PMI_kvsname_max, &PMI_keylen_max, &PMI_vallen_max); + /* we need construct a cmd like "cmd=put kvsname=%s key=%s value=%s\n", + * make sure it fits in PMIU_MAXLINE. + */ + if (PMI_kvsname_max + PMI_keylen_max + PMI_vallen_max + 30 > PMIU_MAXLINE) { + if (PMI_keylen_max > 256) { + PMI_keylen_max = 256; + } + PMI_vallen_max = PMIU_MAXLINE - PMI_kvsname_max - PMI_keylen_max - 30; + assert(PMI_vallen_max > 256); + } /* FIXME: This is something that the PM should tell the process, - rather than deliver it through the environment */ - if ( ( p = getenv( "PMI_SPAWNED" ) ) ) - PMI_spawned = atoi( p ); + * rather than deliver it through the environment */ + if ((p = getenv("PMI_SPAWNED"))) + PMI_spawned = atoi(p); else - PMI_spawned = 0; + PMI_spawned = 0; if (PMI_spawned) - *spawned = 1; + *spawned = 1; else - *spawned = 0; + *spawned = 0; - if ( ! PMI_initialized ) - PMI_initialized = NORMAL_INIT_WITH_PM; + if (!PMI_initialized) + PMI_initialized = NORMAL_INIT_WITH_PM; return PMI_SUCCESS; } -int PMI_Initialized( int *initialized ) +int PMI_Initialized(int *initialized) { /* Turn this into a logical value (1 or 0) . This allows us - to use PMI_initialized to distinguish between initialized with - an PMI service (e.g., via mpiexec) and the singleton init, - which has no PMI service */ + * to use PMI_initialized to distinguish between initialized with + * an PMI service (e.g., via mpiexec) and the singleton init, + * which has no PMI service */ *initialized = (PMI_initialized != 0); return PMI_SUCCESS; } -int PMI_Get_size( int *size ) +int PMI_Get_size(int *size) { - if ( PMI_initialized ) - *size = PMI_size; + if (PMI_initialized) + *size = PMI_size; else - *size = 1; + *size = 1; return PMI_SUCCESS; } -int PMI_Get_rank( int *rank ) +int PMI_Get_rank(int *rank) { - if ( PMI_initialized ) - *rank = PMI_rank; + if (PMI_initialized) + *rank = PMI_rank; else - *rank = 0; + *rank = 0; return PMI_SUCCESS; } -/* +/* * Get_universe_size is one of the routines that needs to communicate * with the process manager. If we started as a singleton init, then - * we first need to connect to the process manager and acquire the + * we first need to connect to the process manager and acquire the * needed information. */ -int PMI_Get_universe_size( int *size) +int PMI_Get_universe_size(int *size) { - int err; + int err; char size_c[PMIU_MAXLINE]; /* Connect to the PM if we haven't already */ - if (PMIi_InitIfSingleton() != 0) return PMI_FAIL; - - if ( PMI_initialized > SINGLETON_INIT_BUT_NO_PM) { - err = GetResponse( "cmd=get_universe_size\n", "universe_size", 0 ); - if (err == PMI_SUCCESS) { - PMIU_getval( "size", size_c, PMIU_MAXLINE ); - *size = atoi(size_c); - return PMI_SUCCESS; - } - else return err; - } - else - *size = 1; + if (PMIi_InitIfSingleton() != 0) + return PMI_FAIL; + + if (PMI_initialized > SINGLETON_INIT_BUT_NO_PM) { + err = GetResponse("cmd=get_universe_size\n", "universe_size", 0); + if (err == PMI_SUCCESS) { + PMIU_getval("size", size_c, PMIU_MAXLINE); + *size = atoi(size_c); + return PMI_SUCCESS; + } else + return err; + } else + *size = 1; return PMI_SUCCESS; } -int PMI_Get_appnum( int *appnum ) +int PMI_Get_appnum(int *appnum) { - int err; + int err; char appnum_c[PMIU_MAXLINE]; - if ( PMI_initialized > SINGLETON_INIT_BUT_NO_PM) { - err = GetResponse( "cmd=get_appnum\n", "appnum", 0 ); - if (err == PMI_SUCCESS) { - PMIU_getval( "appnum", appnum_c, PMIU_MAXLINE ); - *appnum = atoi(appnum_c); - return PMI_SUCCESS; - } - else return err; - - } - else - *appnum = -1; + if (PMI_initialized > SINGLETON_INIT_BUT_NO_PM) { + err = GetResponse("cmd=get_appnum\n", "appnum", 0); + if (err == PMI_SUCCESS) { + PMIU_getval("appnum", appnum_c, PMIU_MAXLINE); + *appnum = atoi(appnum_c); + return PMI_SUCCESS; + } else + return err; + + } else + *appnum = -1; return PMI_SUCCESS; } -int PMI_Barrier( void ) +int PMI_Barrier(void) { int err = PMI_SUCCESS; - if ( PMI_initialized > SINGLETON_INIT_BUT_NO_PM) { - err = GetResponse( "cmd=barrier_in\n", "barrier_out", 0 ); + if (PMI_initialized > SINGLETON_INIT_BUT_NO_PM) { + err = GetResponse("cmd=barrier_in\n", "barrier_out", 0); } return err; } /* Inform the process manager that we're in finalize */ -int PMI_Finalize( void ) +int PMI_Finalize(void) { int err = PMI_SUCCESS; - if ( PMI_initialized > SINGLETON_INIT_BUT_NO_PM) { - err = GetResponse( "cmd=finalize\n", "finalize_ack", 0 ); - shutdown( PMI_fd, SHUT_RDWR ); - close( PMI_fd ); + if (PMI_initialized > SINGLETON_INIT_BUT_NO_PM) { + err = GetResponse("cmd=finalize\n", "finalize_ack", 0); + shutdown(PMI_fd, SHUT_RDWR); + close(PMI_fd); } return err; @@ -325,10 +335,10 @@ int PMI_Abort(int exit_code, const char error_msg[]) char buf[PMIU_MAXLINE]; /* include exit_code in the abort command */ - MPL_snprintf( buf, PMIU_MAXLINE, "cmd=abort exitcode=%d\n", exit_code); + MPL_snprintf(buf, PMIU_MAXLINE, "cmd=abort exitcode=%d\n", exit_code); PMIU_printf(PMI_debug, "aborting job:\n%s\n", error_msg); - GetResponse( buf, "", 0 ); + GetResponse(buf, "", 0); /* the above command should not return */ return PMI_FAIL; @@ -336,79 +346,81 @@ int PMI_Abort(int exit_code, const char error_msg[]) /************************************* Keymap functions **********************/ -/*FIXME: need to return an error if the value of the kvs name returned is +/*FIXME: need to return an error if the value of the kvs name returned is truncated because it is larger than length */ /* FIXME: My name should be cached rather than re-acquired, as it is unchanging (after singleton init) */ -int PMI_KVS_Get_my_name( char kvsname[], int length ) +int PMI_KVS_Get_my_name(char kvsname[], int length) { int err; if (PMI_initialized == SINGLETON_INIT_BUT_NO_PM) { - /* Return a dummy name */ - /* FIXME: We need to support a distinct kvsname for each - process group */ - MPL_snprintf( kvsname, length, "singinit_kvs_%d_0", (int)getpid() ); - return PMI_SUCCESS; + /* Return a dummy name */ + /* FIXME: We need to support a distinct kvsname for each + * process group */ + MPL_snprintf(kvsname, length, "singinit_kvs_%d_0", (int) getpid()); + return PMI_SUCCESS; } - err = GetResponse( "cmd=get_my_kvsname\n", "my_kvsname", 0 ); + err = GetResponse("cmd=get_my_kvsname\n", "my_kvsname", 0); if (err == PMI_SUCCESS) { - PMIU_getval( "kvsname", kvsname, length ); + PMIU_getval("kvsname", kvsname, length); } return err; } -int PMI_KVS_Get_name_length_max( int *maxlen ) +int PMI_KVS_Get_name_length_max(int *maxlen) { if (maxlen == NULL) - return PMI_ERR_INVALID_ARG; + return PMI_ERR_INVALID_ARG; *maxlen = PMI_kvsname_max; return PMI_SUCCESS; } -int PMI_KVS_Get_key_length_max( int *maxlen ) +int PMI_KVS_Get_key_length_max(int *maxlen) { if (maxlen == NULL) - return PMI_ERR_INVALID_ARG; + return PMI_ERR_INVALID_ARG; *maxlen = PMI_keylen_max; return PMI_SUCCESS; } -int PMI_KVS_Get_value_length_max( int *maxlen ) +int PMI_KVS_Get_value_length_max(int *maxlen) { if (maxlen == NULL) - return PMI_ERR_INVALID_ARG; + return PMI_ERR_INVALID_ARG; *maxlen = PMI_vallen_max; return PMI_SUCCESS; } -int PMI_KVS_Put( const char kvsname[], const char key[], const char value[] ) +int PMI_KVS_Put(const char kvsname[], const char key[], const char value[]) { char buf[PMIU_MAXLINE]; - int err = PMI_SUCCESS; - int rc; + int err = PMI_SUCCESS; + int rc; /* This is a special hack to support singleton initialization */ if (PMI_initialized == SINGLETON_INIT_BUT_NO_PM) { if (cached_singinit_inuse) return PMI_FAIL; - rc = MPL_strncpy(cached_singinit_key,key,PMI_keylen_max); - if (rc != 0) return PMI_FAIL; - rc = MPL_strncpy(cached_singinit_val,value,PMI_vallen_max); - if (rc != 0) return PMI_FAIL; + rc = MPL_strncpy(cached_singinit_key, key, PMI_keylen_max); + if (rc != 0) + return PMI_FAIL; + rc = MPL_strncpy(cached_singinit_val, value, PMI_vallen_max); + if (rc != 0) + return PMI_FAIL; cached_singinit_inuse = 1; - return PMI_SUCCESS; + return PMI_SUCCESS; } - - rc = MPL_snprintf( buf, PMIU_MAXLINE, - "cmd=put kvsname=%s key=%s value=%s\n", - kvsname, key, value); - if (rc < 0) return PMI_FAIL; - err = GetResponse( buf, "put_result", 1 ); + + rc = MPL_snprintf(buf, PMIU_MAXLINE, + "cmd=put kvsname=%s key=%s value=%s\n", kvsname, key, value); + if (rc < 0) + return PMI_FAIL; + err = GetResponse(buf, "put_result", 1); return err; } -int PMI_KVS_Commit( const char kvsname[] ATTRIBUTE((unused))) +int PMI_KVS_Commit(const char kvsname[]ATTRIBUTE((unused))) { /* no-op in this implementation */ return PMI_SUCCESS; @@ -416,34 +428,33 @@ int PMI_KVS_Commit( const char kvsname[] ATTRIBUTE((unused))) /*FIXME: need to return an error if the value returned is truncated because it is larger than length */ -int PMI_KVS_Get( const char kvsname[], const char key[], char value[], - int length) +int PMI_KVS_Get(const char kvsname[], const char key[], char value[], int length) { char buf[PMIU_MAXLINE]; int err = PMI_SUCCESS; - int rc; + int rc; /* Connect to the PM if we haven't already. This is needed in case - we're doing an MPI_Comm_join or MPI_Comm_connect/accept from - the singleton init case. This test is here because, in the way in - which MPICH uses PMI, this is where the test needs to be. */ - if (PMIi_InitIfSingleton() != 0) return PMI_FAIL; + * we're doing an MPI_Comm_join or MPI_Comm_connect/accept from + * the singleton init case. This test is here because, in the way in + * which MPICH uses PMI, this is where the test needs to be. */ + if (PMIi_InitIfSingleton() != 0) + return PMI_FAIL; - rc = MPL_snprintf( buf, PMIU_MAXLINE, "cmd=get kvsname=%s key=%s\n", - kvsname, key ); - if (rc < 0) return PMI_FAIL; + rc = MPL_snprintf(buf, PMIU_MAXLINE, "cmd=get kvsname=%s key=%s\n", kvsname, key); + if (rc < 0) + return PMI_FAIL; - err = GetResponse( buf, "get_result", 0 ); + err = GetResponse(buf, "get_result", 0); if (err == PMI_SUCCESS) { - PMIU_getval( "rc", buf, PMIU_MAXLINE ); - rc = atoi( buf ); - if ( rc == 0 ) { - PMIU_getval( "value", value, length ); - return PMI_SUCCESS; - } - else { - return PMI_FAIL; - } + PMIU_getval("rc", buf, PMIU_MAXLINE); + rc = atoi(buf); + if (rc == 0) { + PMIU_getval("value", value, length); + return PMI_SUCCESS; + } else { + return PMI_FAIL; + } } return err; @@ -451,87 +462,78 @@ int PMI_KVS_Get( const char kvsname[], const char key[], char value[], /*************************** Name Publishing functions **********************/ -int PMI_Publish_name( const char service_name[], const char port[] ) +int PMI_Publish_name(const char service_name[], const char port[]) { char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE]; int err; - if ( PMI_initialized > SINGLETON_INIT_BUT_NO_PM) { - MPL_snprintf( cmd, PMIU_MAXLINE, - "cmd=publish_name service=%s port=%s\n", - service_name, port ); - err = GetResponse( cmd, "publish_result", 0 ); - if (err == PMI_SUCCESS) { - PMIU_getval( "rc", buf, PMIU_MAXLINE ); - if ( strcmp(buf,"0") != 0 ) { - PMIU_getval( "msg", buf, PMIU_MAXLINE ); - PMIU_printf( PMI_debug, "publish failed; reason = %s\n", buf ); - - return PMI_FAIL; - } - } - } - else - { - PMIU_printf( 1, "PMI_Publish_name called before init\n" ); - return PMI_FAIL; + if (PMI_initialized > SINGLETON_INIT_BUT_NO_PM) { + MPL_snprintf(cmd, PMIU_MAXLINE, + "cmd=publish_name service=%s port=%s\n", service_name, port); + err = GetResponse(cmd, "publish_result", 0); + if (err == PMI_SUCCESS) { + PMIU_getval("rc", buf, PMIU_MAXLINE); + if (strcmp(buf, "0") != 0) { + PMIU_getval("msg", buf, PMIU_MAXLINE); + PMIU_printf(PMI_debug, "publish failed; reason = %s\n", buf); + + return PMI_FAIL; + } + } + } else { + PMIU_printf(1, "PMI_Publish_name called before init\n"); + return PMI_FAIL; } return PMI_SUCCESS; } -int PMI_Unpublish_name( const char service_name[] ) +int PMI_Unpublish_name(const char service_name[]) { char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE]; int err = PMI_SUCCESS; - if ( PMI_initialized > SINGLETON_INIT_BUT_NO_PM) { - MPL_snprintf( cmd, PMIU_MAXLINE, "cmd=unpublish_name service=%s\n", - service_name ); - err = GetResponse( cmd, "unpublish_result", 0 ); - if (err == PMI_SUCCESS) { - PMIU_getval( "rc", buf, PMIU_MAXLINE ); - if ( strcmp(buf,"0") != 0 ) { - PMIU_getval( "msg", buf, PMIU_MAXLINE ); - PMIU_printf( PMI_debug, "unpublish failed; reason = %s\n", buf ); + if (PMI_initialized > SINGLETON_INIT_BUT_NO_PM) { + MPL_snprintf(cmd, PMIU_MAXLINE, "cmd=unpublish_name service=%s\n", service_name); + err = GetResponse(cmd, "unpublish_result", 0); + if (err == PMI_SUCCESS) { + PMIU_getval("rc", buf, PMIU_MAXLINE); + if (strcmp(buf, "0") != 0) { + PMIU_getval("msg", buf, PMIU_MAXLINE); + PMIU_printf(PMI_debug, "unpublish failed; reason = %s\n", buf); return PMI_FAIL; - } - } - } - else - { - PMIU_printf( 1, "PMI_Unpublish_name called before init\n" ); - return PMI_FAIL; + } + } + } else { + PMIU_printf(1, "PMI_Unpublish_name called before init\n"); + return PMI_FAIL; } return PMI_SUCCESS; } -int PMI_Lookup_name( const char service_name[], char port[] ) +int PMI_Lookup_name(const char service_name[], char port[]) { char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE]; int err; - if ( PMI_initialized > SINGLETON_INIT_BUT_NO_PM) { - MPL_snprintf( cmd, PMIU_MAXLINE, "cmd=lookup_name service=%s\n", - service_name ); - err = GetResponse( cmd, "lookup_result", 0 ); - if (err == PMI_SUCCESS) { - PMIU_getval( "rc", buf, PMIU_MAXLINE ); - if ( strcmp(buf,"0") != 0 ) { - PMIU_getval( "msg", buf, PMIU_MAXLINE ); - PMIU_printf( PMI_debug, "lookup failed; reason = %s\n", buf ); - - return PMI_FAIL; - } - PMIU_getval( "port", port, MPI_MAX_PORT_NAME ); - } - } - else - { - PMIU_printf( 1, "PMI_Lookup_name called before init\n" ); - return PMI_FAIL; + if (PMI_initialized > SINGLETON_INIT_BUT_NO_PM) { + MPL_snprintf(cmd, PMIU_MAXLINE, "cmd=lookup_name service=%s\n", service_name); + err = GetResponse(cmd, "lookup_result", 0); + if (err == PMI_SUCCESS) { + PMIU_getval("rc", buf, PMIU_MAXLINE); + if (strcmp(buf, "0") != 0) { + PMIU_getval("msg", buf, PMIU_MAXLINE); + PMIU_printf(PMI_debug, "lookup failed; reason = %s\n", buf); + + return PMI_FAIL; + } + PMIU_getval("port", port, MPI_MAX_PORT_NAME); + } + } else { + PMIU_printf(1, "PMI_Lookup_name called before init\n"); + return PMI_FAIL; } return PMI_SUCCESS; @@ -541,193 +543,183 @@ int PMI_Lookup_name( const char service_name[], char port[] ) /************************** Process Creation functions **********************/ int PMI_Spawn_multiple(int count, - const char * cmds[], - const char ** argvs[], + const char *cmds[], + const char **argvs[], const int maxprocs[], const int info_keyval_sizes[], const PMI_keyval_t * info_keyval_vectors[], int preput_keyval_size, - const PMI_keyval_t preput_keyval_vector[], - int errors[]) + const PMI_keyval_t preput_keyval_vector[], int errors[]) { - int i,rc,argcnt,spawncnt,total_num_processes,num_errcodes_found; + int i, rc, argcnt, spawncnt, total_num_processes, num_errcodes_found; char buf[PMIU_MAXLINE], tempbuf[PMIU_MAXLINE], cmd[PMIU_MAXLINE]; char *lead, *lag; /* Connect to the PM if we haven't already */ - if (PMIi_InitIfSingleton() != 0) return PMI_FAIL; + if (PMIi_InitIfSingleton() != 0) + return PMI_FAIL; total_num_processes = 0; - for (spawncnt=0; spawncnt < count; spawncnt++) - { + for (spawncnt = 0; spawncnt < count; spawncnt++) { total_num_processes += maxprocs[spawncnt]; - rc = MPL_snprintf(buf, PMIU_MAXLINE, - "mcmd=spawn\nnprocs=%d\nexecname=%s\n", - maxprocs[spawncnt], cmds[spawncnt] ); - if (rc < 0) { - return PMI_FAIL; - } - - rc = MPL_snprintf(tempbuf, PMIU_MAXLINE, - "totspawns=%d\nspawnssofar=%d\n", - count, spawncnt+1); - - if (rc < 0) { - return PMI_FAIL; - } - rc = MPL_strnapp(buf,tempbuf,PMIU_MAXLINE); - if (rc != 0) { - return PMI_FAIL; - } + rc = MPL_snprintf(buf, PMIU_MAXLINE, + "mcmd=spawn\nnprocs=%d\nexecname=%s\n", + maxprocs[spawncnt], cmds[spawncnt]); + if (rc < 0) { + return PMI_FAIL; + } + + rc = MPL_snprintf(tempbuf, PMIU_MAXLINE, + "totspawns=%d\nspawnssofar=%d\n", count, spawncnt + 1); + + if (rc < 0) { + return PMI_FAIL; + } + rc = MPL_strnapp(buf, tempbuf, PMIU_MAXLINE); + if (rc != 0) { + return PMI_FAIL; + } argcnt = 0; if ((argvs != NULL) && (argvs[spawncnt] != NULL)) { - for (i=0; argvs[spawncnt][i] != NULL; i++) - { - /* FIXME (protocol design flaw): command line arguments - may contain both = and (and even tab!). - */ - /* Note that part of this fixme was really a design error - - because this uses the mcmd form, the data can be - sent in multiple writelines. This code now takes - advantage of that. Note also that a correct parser - of the commands will permit any character other than a - new line in the argument, since the form is - argn= */ - rc = MPL_snprintf(tempbuf,PMIU_MAXLINE,"arg%d=%s\n", - i+1,argvs[spawncnt][i]); - if (rc < 0) { - return PMI_FAIL; - } - rc = MPL_strnapp(buf,tempbuf,PMIU_MAXLINE); - if (rc != 0) { - return PMI_FAIL; - } + for (i = 0; argvs[spawncnt][i] != NULL; i++) { + /* FIXME (protocol design flaw): command line arguments + * may contain both = and (and even tab!). + */ + /* Note that part of this fixme was really a design error - + * because this uses the mcmd form, the data can be + * sent in multiple writelines. This code now takes + * advantage of that. Note also that a correct parser + * of the commands will permit any character other than a + * new line in the argument, since the form is + * argn= */ + rc = MPL_snprintf(tempbuf, PMIU_MAXLINE, "arg%d=%s\n", i + 1, argvs[spawncnt][i]); + if (rc < 0) { + return PMI_FAIL; + } + rc = MPL_strnapp(buf, tempbuf, PMIU_MAXLINE); + if (rc != 0) { + return PMI_FAIL; + } argcnt++; - rc = PMIU_writeline( PMI_fd, buf ); + rc = PMIU_writeline(PMI_fd, buf); if (rc) return PMI_FAIL; - buf[0] = 0; + buf[0] = 0; + + } + } + rc = MPL_snprintf(tempbuf, PMIU_MAXLINE, "argcnt=%d\n", argcnt); + if (rc < 0) { + return PMI_FAIL; + } + rc = MPL_strnapp(buf, tempbuf, PMIU_MAXLINE); + if (rc != 0) { + return PMI_FAIL; + } + + rc = MPL_snprintf(tempbuf, PMIU_MAXLINE, "preput_num=%d\n", preput_keyval_size); + if (rc < 0) { + return PMI_FAIL; + } + rc = MPL_strnapp(buf, tempbuf, PMIU_MAXLINE); + if (rc != 0) { + return PMI_FAIL; + } + for (i = 0; i < preput_keyval_size; i++) { + rc = MPL_snprintf(tempbuf, PMIU_MAXLINE, "preput_key_%d=%s\n", + i, preput_keyval_vector[i].key); + if (rc < 0) { + return PMI_FAIL; + } + rc = MPL_strnapp(buf, tempbuf, PMIU_MAXLINE); + if (rc != 0) { + return PMI_FAIL; + } + rc = MPL_snprintf(tempbuf, PMIU_MAXLINE, "preput_val_%d=%s\n", + i, preput_keyval_vector[i].val); + if (rc < 0) { + return PMI_FAIL; + } + rc = MPL_strnapp(buf, tempbuf, PMIU_MAXLINE); + if (rc != 0) { + return PMI_FAIL; + } + } + rc = MPL_snprintf(tempbuf, PMIU_MAXLINE, "info_num=%d\n", info_keyval_sizes[spawncnt]); + if (rc < 0) { + return PMI_FAIL; + } + rc = MPL_strnapp(buf, tempbuf, PMIU_MAXLINE); + if (rc != 0) { + return PMI_FAIL; + } + for (i = 0; i < info_keyval_sizes[spawncnt]; i++) { + rc = MPL_snprintf(tempbuf, PMIU_MAXLINE, "info_key_%d=%s\n", + i, info_keyval_vectors[spawncnt][i].key); + if (rc < 0) { + return PMI_FAIL; + } + rc = MPL_strnapp(buf, tempbuf, PMIU_MAXLINE); + if (rc != 0) { + return PMI_FAIL; + } + rc = MPL_snprintf(tempbuf, PMIU_MAXLINE, "info_val_%d=%s\n", + i, info_keyval_vectors[spawncnt][i].val); + if (rc < 0) { + return PMI_FAIL; + } + rc = MPL_strnapp(buf, tempbuf, PMIU_MAXLINE); + if (rc != 0) { + return PMI_FAIL; } } - rc = MPL_snprintf(tempbuf,PMIU_MAXLINE,"argcnt=%d\n",argcnt); - if (rc < 0) { - return PMI_FAIL; - } - rc = MPL_strnapp(buf,tempbuf,PMIU_MAXLINE); - if (rc != 0) { - return PMI_FAIL; - } - - rc = MPL_snprintf(tempbuf,PMIU_MAXLINE,"preput_num=%d\n", - preput_keyval_size); - if (rc < 0) { - return PMI_FAIL; - } - - rc = MPL_strnapp(buf,tempbuf,PMIU_MAXLINE); - if (rc != 0) { - return PMI_FAIL; - } - for (i=0; i < preput_keyval_size; i++) { - rc = MPL_snprintf(tempbuf,PMIU_MAXLINE,"preput_key_%d=%s\n", - i,preput_keyval_vector[i].key); - if (rc < 0) { - return PMI_FAIL; - } - rc = MPL_strnapp(buf,tempbuf,PMIU_MAXLINE); - if (rc != 0) { - return PMI_FAIL; - } - rc = MPL_snprintf(tempbuf,PMIU_MAXLINE,"preput_val_%d=%s\n", - i,preput_keyval_vector[i].val); - if (rc < 0) { - return PMI_FAIL; - } - rc = MPL_strnapp(buf,tempbuf,PMIU_MAXLINE); - if (rc != 0) { - return PMI_FAIL; - } - } - rc = MPL_snprintf(tempbuf,PMIU_MAXLINE,"info_num=%d\n", - info_keyval_sizes[spawncnt]); - if (rc < 0) { - return PMI_FAIL; - } - rc = MPL_strnapp(buf,tempbuf,PMIU_MAXLINE); - if (rc != 0) { - return PMI_FAIL; - } - for (i=0; i < info_keyval_sizes[spawncnt]; i++) - { - rc = MPL_snprintf(tempbuf,PMIU_MAXLINE,"info_key_%d=%s\n", - i,info_keyval_vectors[spawncnt][i].key); - if (rc < 0) { - return PMI_FAIL; - } - rc = MPL_strnapp(buf,tempbuf,PMIU_MAXLINE); - if (rc != 0) { - return PMI_FAIL; - } - rc = MPL_snprintf(tempbuf,PMIU_MAXLINE,"info_val_%d=%s\n", - i,info_keyval_vectors[spawncnt][i].val); - if (rc < 0) { - return PMI_FAIL; - } - rc = MPL_strnapp(buf,tempbuf,PMIU_MAXLINE); - if (rc != 0) { - return PMI_FAIL; - } - } rc = MPL_strnapp(buf, "endcmd\n", PMIU_MAXLINE); - if (rc != 0) { - return PMI_FAIL; - } - rc = PMIU_writeline( PMI_fd, buf ); - if (rc) { - return PMI_FAIL; - } + if (rc != 0) { + return PMI_FAIL; + } + rc = PMIU_writeline(PMI_fd, buf); + if (rc) { + return PMI_FAIL; + } } - PMIU_readline( PMI_fd, buf, PMIU_MAXLINE ); - PMIU_parse_keyvals( buf ); - PMIU_getval( "cmd", cmd, PMIU_MAXLINE ); - if ( strncmp( cmd, "spawn_result", PMIU_MAXLINE ) != 0 ) { - PMIU_printf( 1, "got unexpected response to spawn :%s:\n", buf ); - return PMI_FAIL; - } - else { - PMIU_getval( "rc", buf, PMIU_MAXLINE ); - rc = atoi( buf ); - if ( rc != 0 ) { - /**** - PMIU_getval( "status", tempbuf, PMIU_MAXLINE ); - PMIU_printf( 1, "pmi_spawn_mult failed; status: %s\n",tempbuf); - ****/ - return PMI_FAIL; - } + PMIU_readline(PMI_fd, buf, PMIU_MAXLINE); + PMIU_parse_keyvals(buf); + PMIU_getval("cmd", cmd, PMIU_MAXLINE); + if (strncmp(cmd, "spawn_result", PMIU_MAXLINE) != 0) { + PMIU_printf(1, "got unexpected response to spawn :%s:\n", buf); + return PMI_FAIL; + } else { + PMIU_getval("rc", buf, PMIU_MAXLINE); + rc = atoi(buf); + if (rc != 0) { + /* PMIU_getval("status", tempbuf, PMIU_MAXLINE); */ + /* PMIU_printf(1, "pmi_spawn_mult failed; status: %s\n",tempbuf); */ + return PMI_FAIL; + } } - + PMIU_Assert(errors != NULL); - if (PMIU_getval( "errcodes", tempbuf, PMIU_MAXLINE )) { + if (PMIU_getval("errcodes", tempbuf, PMIU_MAXLINE)) { num_errcodes_found = 0; lag = &tempbuf[0]; do { lead = strchr(lag, ','); - if (lead) *lead = '\0'; + if (lead) + *lead = '\0'; errors[num_errcodes_found++] = atoi(lag); - lag = lead + 1; /* move past the null char */ + lag = lead + 1; /* move past the null char */ PMIU_Assert(num_errcodes_found <= total_num_processes); } while (lead != NULL); PMIU_Assert(num_errcodes_found == total_num_processes); - } - else { + } else { /* gforker doesn't return errcodes, so we'll just pretend that means - that it was going to send all `0's. */ + * that it was going to send all `0's. */ for (i = 0; i < total_num_processes; ++i) { errors[i] = 0; } @@ -740,65 +732,66 @@ int PMI_Spawn_multiple(int count, /* to get all maxes in one message */ /* FIXME: This mixes init with get maxes */ -static int PMII_getmaxes( int *kvsname_max, int *keylen_max, int *vallen_max ) +static int PMII_getmaxes(int *kvsname_max, int *keylen_max, int *vallen_max) { - char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE], errmsg[PMIU_MAXLINE]; + char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE]; int err, rc; - rc = MPL_snprintf( buf, PMIU_MAXLINE, - "cmd=init pmi_version=%d pmi_subversion=%d\n", - PMI_VERSION, PMI_SUBVERSION ); + rc = MPL_snprintf(buf, PMIU_MAXLINE, + "cmd=init pmi_version=%d pmi_subversion=%d\n", PMI_VERSION, PMI_SUBVERSION); if (rc < 0) { - return PMI_FAIL; + return PMI_FAIL; } - rc = PMIU_writeline( PMI_fd, buf ); + rc = PMIU_writeline(PMI_fd, buf); if (rc != 0) { - PMIU_printf( 1, "Unable to write to PMI_fd\n" ); - return PMI_FAIL; + PMIU_printf(1, "Unable to write to PMI_fd\n"); + return PMI_FAIL; } - buf[0] = 0; /* Ensure buffer is empty if read fails */ - err = PMIU_readline( PMI_fd, buf, PMIU_MAXLINE ); + buf[0] = 0; /* Ensure buffer is empty if read fails */ + err = PMIU_readline(PMI_fd, buf, PMIU_MAXLINE); if (err < 0) { - PMIU_printf( 1, "Error reading initack on %d\n", PMI_fd ); - perror( "Error on readline:" ); - PMI_Abort(-1, "Above error when reading after init" ); + PMIU_printf(1, "Error reading initack on %d\n", PMI_fd); + perror("Error on readline:"); + PMI_Abort(-1, "Above error when reading after init"); } - PMIU_parse_keyvals( buf ); + PMIU_parse_keyvals(buf); cmd[0] = 0; - PMIU_getval( "cmd", cmd, PMIU_MAXLINE ); - if ( strncmp( cmd, "response_to_init", PMIU_MAXLINE ) != 0 ) { - MPL_snprintf(errmsg, PMIU_MAXLINE, - "got unexpected response to init :%s: (full line = %s)", - cmd, buf ); - PMI_Abort( -1, errmsg ); - } - else { - char buf1[PMIU_MAXLINE]; - PMIU_getval( "rc", buf, PMIU_MAXLINE ); - if ( strncmp( buf, "0", PMIU_MAXLINE ) != 0 ) { - PMIU_getval( "pmi_version", buf, PMIU_MAXLINE ); - PMIU_getval( "pmi_subversion", buf1, PMIU_MAXLINE ); - MPL_snprintf(errmsg, PMIU_MAXLINE, - "pmi_version mismatch; client=%d.%d mgr=%s.%s", - PMI_VERSION, PMI_SUBVERSION, buf, buf1 ); - PMI_Abort( -1, errmsg ); + PMIU_getval("cmd", cmd, PMIU_MAXLINE); + + if (strncmp(cmd, "response_to_init", PMIU_MAXLINE) != 0) { + char errmsg[PMIU_MAXLINE * 2 + 100]; + MPL_snprintf(errmsg, sizeof(errmsg), + "got unexpected response to init :%s: (full line = %s)", cmd, buf); + PMI_Abort(-1, errmsg); + } else { + char buf1[PMIU_MAXLINE]; + PMIU_getval("rc", buf, PMIU_MAXLINE); + if (strncmp(buf, "0", PMIU_MAXLINE) != 0) { + PMIU_getval("pmi_version", buf, PMIU_MAXLINE); + PMIU_getval("pmi_subversion", buf1, PMIU_MAXLINE); + + char errmsg[PMIU_MAXLINE * 2 + 100]; + MPL_snprintf(errmsg, sizeof(errmsg), + "pmi_version mismatch; client=%d.%d mgr=%s.%s", + PMI_VERSION, PMI_SUBVERSION, buf, buf1); + PMI_Abort(-1, errmsg); } } - err = GetResponse( "cmd=get_maxes\n", "maxes", 0 ); + err = GetResponse("cmd=get_maxes\n", "maxes", 0); if (err == PMI_SUCCESS) { - PMIU_getval( "kvsname_max", buf, PMIU_MAXLINE ); - *kvsname_max = atoi( buf ); - PMIU_getval( "keylen_max", buf, PMIU_MAXLINE ); - *keylen_max = atoi( buf ); - PMIU_getval( "vallen_max", buf, PMIU_MAXLINE ); - *vallen_max = atoi( buf ); + PMIU_getval("kvsname_max", buf, PMIU_MAXLINE); + *kvsname_max = atoi(buf); + PMIU_getval("keylen_max", buf, PMIU_MAXLINE); + *keylen_max = atoi(buf); + PMIU_getval("vallen_max", buf, PMIU_MAXLINE); + *vallen_max = atoi(buf); } return err; } /* ----------------------------------------------------------------------- */ -/* +/* * This function is used to request information from the server and check * that the response uses the expected command name. On a successful * return from this routine, additional PMIU_getval calls may be used @@ -808,8 +801,7 @@ static int PMII_getmaxes( int *kvsname_max, int *keylen_max, int *vallen_max ) * was 0. If not, it uses the "msg" value to report on the reason for * the failure. */ -static int GetResponse( const char request[], const char expectedCmd[], - int checkRc ) +static int GetResponse(const char request[], const char expectedCmd[], int checkRc) { int err, n; char *p; @@ -817,44 +809,44 @@ static int GetResponse( const char request[], const char expectedCmd[], char cmdName[PMIU_MAXLINE]; /* FIXME: This is an example of an incorrect fix - writeline can change - the second argument in some cases, and that will break the const'ness - of request. Instead, writeline should take a const item and return - an error in the case in which it currently truncates the data. */ - err = PMIU_writeline( PMI_fd, (char *)request ); + * the second argument in some cases, and that will break the const'ness + * of request. Instead, writeline should take a const item and return + * an error in the case in which it currently truncates the data. */ + err = PMIU_writeline(PMI_fd, (char *) request); if (err) { - return err; + return err; } - n = PMIU_readline( PMI_fd, recvbuf, sizeof(recvbuf) ); + n = PMIU_readline(PMI_fd, recvbuf, sizeof(recvbuf)); if (n <= 0) { - PMIU_printf( 1, "readline failed\n" ); - return PMI_FAIL; + PMIU_printf(1, "readline failed\n"); + return PMI_FAIL; } - err = PMIU_parse_keyvals( recvbuf ); + err = PMIU_parse_keyvals(recvbuf); if (err) { - PMIU_printf( 1, "parse_kevals failed %d\n", err ); - return err; + PMIU_printf(1, "parse_kevals failed %d\n", err); + return err; } - p = PMIU_getval( "cmd", cmdName, sizeof(cmdName) ); + p = PMIU_getval("cmd", cmdName, sizeof(cmdName)); if (!p) { - PMIU_printf( 1, "getval cmd failed\n" ); - return PMI_FAIL; + PMIU_printf(1, "getval cmd failed\n"); + return PMI_FAIL; } - if (strcmp( expectedCmd, cmdName ) != 0) { - PMIU_printf( 1, "expecting cmd=%s, got %s\n", expectedCmd, cmdName ); - return PMI_FAIL; + if (strcmp(expectedCmd, cmdName) != 0) { + PMIU_printf(1, "expecting cmd=%s, got %s\n", expectedCmd, cmdName); + return PMI_FAIL; } if (checkRc) { - p = PMIU_getval( "rc", cmdName, PMIU_MAXLINE ); - if ( p && strcmp(cmdName,"0") != 0 ) { - PMIU_getval( "msg", cmdName, PMIU_MAXLINE ); - PMIU_printf( 1, "Command %s failed, reason='%s'\n", - request, cmdName ); - return PMI_FAIL; - } + p = PMIU_getval("rc", cmdName, PMIU_MAXLINE); + if (p && strcmp(cmdName, "0") != 0) { + PMIU_getval("msg", cmdName, PMIU_MAXLINE); + PMIU_printf(1, "Command %s failed, reason='%s'\n", request, cmdName); + return PMI_FAIL; + } } return err; } + /* ----------------------------------------------------------------------- */ @@ -888,73 +880,63 @@ static int GetResponse( const char request[], const char expectedCmd[], #define TCP 0 #endif -/* stub for connecting to a specified host/port instead of using a +/* stub for connecting to a specified host/port instead of using a specified fd inherited from a parent process */ -static int PMII_Connect_to_pm( char *hostname, int portnum ) +static int PMII_Connect_to_pm(char *hostname, int portnum) { - struct hostent *hp; - struct sockaddr_in sa; - int fd; - int optval = 1; - int q_wait = 1; - - hp = gethostbyname( hostname ); - if (!hp) { - PMIU_printf( 1, "Unable to get host entry for %s\n", hostname ); - return PMI_FAIL; + MPL_sockaddr_t addr; + int ret; + int fd; + int optval = 1; + int q_wait = 1; + + ret = MPL_get_sockaddr(hostname, &addr); + if (ret) { + PMIU_printf(1, "Unable to get host entry for %s\n", hostname); + return PMI_FAIL; } - - memset( (void *)&sa, 0, sizeof(sa) ); - /* POSIX might define h_addr_list only and node define h_addr */ -#ifdef HAVE_H_ADDR_LIST - memcpy( (void *)&sa.sin_addr, (void *)hp->h_addr_list[0], hp->h_length); -#else - memcpy( (void *)&sa.sin_addr, (void *)hp->h_addr, hp->h_length); -#endif - sa.sin_family = hp->h_addrtype; - sa.sin_port = htons( (unsigned short) portnum ); - - fd = socket( AF_INET, SOCK_STREAM, TCP ); + + fd = MPL_socket(); if (fd < 0) { - PMIU_printf( 1, "Unable to get AF_INET socket\n" ); - return PMI_FAIL; + PMIU_printf(1, "Unable to get AF_INET socket\n"); + return PMI_FAIL; } - - if (setsockopt( fd, IPPROTO_TCP, TCP_NODELAY, - (char *)&optval, sizeof(optval) )) { - perror( "Error calling setsockopt:" ); + + if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &optval, sizeof(optval))) { + perror("Error calling setsockopt:"); } /* We wait here for the connection to succeed */ - if (connect( fd, (struct sockaddr *)&sa, sizeof(sa) ) < 0) { - switch (errno) { - case ECONNREFUSED: - PMIU_printf( 1, "connect failed with connection refused\n" ); - /* (close socket, get new socket, try again) */ - if (q_wait) - close(fd); - return PMI_FAIL; - - case EINPROGRESS: /* (nonblocking) - select for writing. */ - break; - - case EISCONN: /* (already connected) */ - break; - - case ETIMEDOUT: /* timed out */ - PMIU_printf( 1, "connect failed with timeout\n" ); - return PMI_FAIL; - - default: - PMIU_printf( 1, "connect failed with errno %d\n", errno ); - return PMI_FAIL; - } + ret = MPL_connect(fd, &addr, portnum); + if (ret < 0) { + switch (errno) { + case ECONNREFUSED: + PMIU_printf(1, "connect failed with connection refused\n"); + /* (close socket, get new socket, try again) */ + if (q_wait) + close(fd); + return PMI_FAIL; + + case EINPROGRESS: /* (nonblocking) - select for writing. */ + break; + + case EISCONN: /* (already connected) */ + break; + + case ETIMEDOUT: /* timed out */ + PMIU_printf(1, "connect failed with timeout\n"); + return PMI_FAIL; + + default: + PMIU_printf(1, "connect failed with errno %d\n", errno); + return PMI_FAIL; + } } return fd; } -static int PMII_Set_from_port( int fd, int id ) +static int PMII_Set_from_port(int fd, int id) { char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE]; int err, rc; @@ -962,115 +944,114 @@ static int PMII_Set_from_port( int fd, int id ) /* We start by sending a startup message to the server */ if (PMI_debug) { - PMIU_printf( 1, "Writing initack to destination fd %d\n", fd ); + PMIU_printf(1, "Writing initack to destination fd %d\n", fd); } /* Handshake and initialize from a port */ - rc = MPL_snprintf( buf, PMIU_MAXLINE, "cmd=initack pmiid=%d\n", id ); + rc = MPL_snprintf(buf, PMIU_MAXLINE, "cmd=initack pmiid=%d\n", id); if (rc < 0) { - return PMI_FAIL; + return PMI_FAIL; } - PMIU_printf( PMI_debug, "writing on fd %d line :%s:\n", fd, buf ); - err = PMIU_writeline( fd, buf ); + PMIU_printf(PMI_debug, "writing on fd %d line :%s:\n", fd, buf); + err = PMIU_writeline(fd, buf); if (err) { - PMIU_printf( 1, "Error in writeline initack\n" ); - return PMI_FAIL; + PMIU_printf(1, "Error in writeline initack\n"); + return PMI_FAIL; } /* cmd=initack */ buf[0] = 0; - PMIU_printf( PMI_debug, "reading initack\n" ); - err = PMIU_readline( fd, buf, PMIU_MAXLINE ); + PMIU_printf(PMI_debug, "reading initack\n"); + err = PMIU_readline(fd, buf, PMIU_MAXLINE); if (err < 0) { - PMIU_printf( 1, "Error reading initack on %d\n", fd ); - perror( "Error on readline:" ); - return PMI_FAIL; + PMIU_printf(1, "Error reading initack on %d\n", fd); + perror("Error on readline:"); + return PMI_FAIL; } - PMIU_parse_keyvals( buf ); - PMIU_getval( "cmd", cmd, PMIU_MAXLINE ); - if ( strcmp( cmd, "initack" ) ) { - PMIU_printf( 1, "got unexpected input %s\n", buf ); - return PMI_FAIL; + PMIU_parse_keyvals(buf); + PMIU_getval("cmd", cmd, PMIU_MAXLINE); + if (strcmp(cmd, "initack")) { + PMIU_printf(1, "got unexpected input %s\n", buf); + return PMI_FAIL; } - - /* Read, in order, size, rank, and debug. Eventually, we'll want - the handshake to include a version number */ + + /* Read, in order, size, rank, and debug. Eventually, we'll want + * the handshake to include a version number */ /* size */ - PMIU_printf( PMI_debug, "reading size\n" ); - err = PMIU_readline( fd, buf, PMIU_MAXLINE ); + PMIU_printf(PMI_debug, "reading size\n"); + err = PMIU_readline(fd, buf, PMIU_MAXLINE); if (err < 0) { - PMIU_printf( 1, "Error reading size on %d\n", fd ); - perror( "Error on readline:" ); - return PMI_FAIL; + PMIU_printf(1, "Error reading size on %d\n", fd); + perror("Error on readline:"); + return PMI_FAIL; } - PMIU_parse_keyvals( buf ); - PMIU_getval( "cmd", cmd, PMIU_MAXLINE ); - if ( strcmp(cmd,"set")) { - PMIU_printf( 1, "got unexpected command %s in %s\n", cmd, buf ); - return PMI_FAIL; + PMIU_parse_keyvals(buf); + PMIU_getval("cmd", cmd, PMIU_MAXLINE); + if (strcmp(cmd, "set")) { + PMIU_printf(1, "got unexpected command %s in %s\n", cmd, buf); + return PMI_FAIL; } /* cmd=set size=n */ - PMIU_getval( "size", cmd, PMIU_MAXLINE ); + PMIU_getval("size", cmd, PMIU_MAXLINE); PMI_size = atoi(cmd); /* rank */ - PMIU_printf( PMI_debug, "reading rank\n" ); - err = PMIU_readline( fd, buf, PMIU_MAXLINE ); + PMIU_printf(PMI_debug, "reading rank\n"); + err = PMIU_readline(fd, buf, PMIU_MAXLINE); if (err < 0) { - PMIU_printf( 1, "Error reading rank on %d\n", fd ); - perror( "Error on readline:" ); - return PMI_FAIL; + PMIU_printf(1, "Error reading rank on %d\n", fd); + perror("Error on readline:"); + return PMI_FAIL; } - PMIU_parse_keyvals( buf ); - PMIU_getval( "cmd", cmd, PMIU_MAXLINE ); - if ( strcmp(cmd,"set")) { - PMIU_printf( 1, "got unexpected command %s in %s\n", cmd, buf ); - return PMI_FAIL; + PMIU_parse_keyvals(buf); + PMIU_getval("cmd", cmd, PMIU_MAXLINE); + if (strcmp(cmd, "set")) { + PMIU_printf(1, "got unexpected command %s in %s\n", cmd, buf); + return PMI_FAIL; } /* cmd=set rank=n */ - PMIU_getval( "rank", cmd, PMIU_MAXLINE ); + PMIU_getval("rank", cmd, PMIU_MAXLINE); PMI_rank = atoi(cmd); - PMIU_Set_rank( PMI_rank ); + PMIU_Set_rank(PMI_rank); /* debug flag */ - err = PMIU_readline( fd, buf, PMIU_MAXLINE ); + err = PMIU_readline(fd, buf, PMIU_MAXLINE); if (err < 0) { - PMIU_printf( 1, "Error reading debug on %d\n", fd ); - return PMI_FAIL; + PMIU_printf(1, "Error reading debug on %d\n", fd); + return PMI_FAIL; } - PMIU_parse_keyvals( buf ); - PMIU_getval( "cmd", cmd, PMIU_MAXLINE ); - if ( strcmp(cmd,"set")) { - PMIU_printf( 1, "got unexpected command %s in %s\n", cmd, buf ); - return PMI_FAIL; + PMIU_parse_keyvals(buf); + PMIU_getval("cmd", cmd, PMIU_MAXLINE); + if (strcmp(cmd, "set")) { + PMIU_printf(1, "got unexpected command %s in %s\n", cmd, buf); + return PMI_FAIL; } /* cmd=set debug=n */ - PMIU_getval( "debug", cmd, PMIU_MAXLINE ); + PMIU_getval("debug", cmd, PMIU_MAXLINE); PMI_debug = atoi(cmd); if (PMI_debug) { - DBG_PRINTF( ("end of handshake, rank = %d, size = %d\n", - PMI_rank, PMI_size )); - DBG_PRINTF( ("Completed init\n" ) ); + DBG_PRINTF(("end of handshake, rank = %d, size = %d\n", PMI_rank, PMI_size)); + DBG_PRINTF(("Completed init\n")); } return PMI_SUCCESS; } /* ------------------------------------------------------------------------- */ -/* +/* * Singleton Init. - * + * * MPI-2 allows processes to become MPI processes and then make MPI calls, - * such as MPI_Comm_spawn, that require a process manager (this is different - * than the much simpler case of allowing MPI programs to run with an + * such as MPI_Comm_spawn, that require a process manager (this is different + * than the much simpler case of allowing MPI programs to run with an * MPI_COMM_WORLD of size 1 without an mpiexec or process manager). * * The process starts when either the client or the process manager contacts * the other. If the client starts, it sends a singinit command and * waits for the server to respond with its own singinit command. - * If the server start, it send a singinit command and waits for the + * If the server start, it send a singinit command and waits for the * client to respond with its own singinit command * * client sends singinit with these required values @@ -1097,20 +1078,20 @@ static int PMII_Set_from_port( int fd, int id ) * * cmd=init pmi_version= pmi_subversion= * - * and expects to receive a + * and expects to receive a * - * cmd=response_to_init rc=0 pmi_version= pmi_subversion= + * cmd=response_to_init rc=0 pmi_version= pmi_subversion= * * (This is the usual init sequence). * */ /* ------------------------------------------------------------------------- */ -/* This is a special routine used to re-initialize PMI when it is in - the singleton init case. That is, the executable was started without +/* This is a special routine used to re-initialize PMI when it is in + the singleton init case. That is, the executable was started without mpiexec, and PMI_Init returned as if there was only one process. Note that PMI routines should not call PMII_singinit; they should - call PMIi_InitIfSingleton(), which both connects to the process mangager + call PMIi_InitIfSingleton(), which both connects to the process manager and sets up the initial KVS connection entry. */ @@ -1120,135 +1101,114 @@ static int PMII_singinit(void) int singinit_listen_sock, stdin_sock, stdout_sock, stderr_sock; const char *newargv[8]; char charpid[8], port_c[8]; - struct sockaddr_in sin; - socklen_t len; + unsigned short port; /* Create a socket on which to allow an mpiexec to connect back to - us */ - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = INADDR_ANY; - sin.sin_port = htons(0); /* anonymous port */ - - singinit_listen_sock = socket(AF_INET, SOCK_STREAM, 0); + * us */ + singinit_listen_sock = MPL_socket(); if (singinit_listen_sock == -1) { perror("PMII_singinit: socket creation failed"); return PMI_FAIL; } - rc = bind(singinit_listen_sock, (struct sockaddr *)&sin ,sizeof(sin)); - if (rc == -1) { - perror("PMII_singinit: socket bind failed"); - return PMI_FAIL; - } - - len = sizeof(struct sockaddr_in); - rc = getsockname( singinit_listen_sock, (struct sockaddr *) &sin, &len ); - if (rc == -1) { - perror("PMII_singinit: getsockname failed"); - return PMI_FAIL; - } - - MPL_snprintf(port_c, sizeof(port_c), "%d",ntohs(sin.sin_port)); - rc = listen(singinit_listen_sock, 5); - if (rc == -1) { + MPL_LISTEN_PUSH(0, 5); + rc = MPL_listen_anyport(singinit_listen_sock, &port); + MPL_LISTEN_POP; + if (rc) { perror("PMII_singinit: listen failed"); return PMI_FAIL; } + MPL_snprintf(port_c, sizeof(port_c), "%d", port); - PMIU_printf( PMI_debug_init, "Starting mpiexec with %s\n", port_c ); + PMIU_printf(PMI_debug_init, "Starting mpiexec with %s\n", port_c); /* Launch the mpiexec process with the name of this port */ pid = fork(); if (pid < 0) { - perror("PMII_singinit: fork failed"); - exit(-1); - } - else if (pid == 0) { - newargv[0] = "mpiexec"; - newargv[1] = "-pmi_args"; - newargv[2] = port_c; - /* FIXME: Use a valid hostname */ - newargv[3] = "default_interface"; /* default interface name, for now */ - newargv[4] = "default_key"; /* default authentication key, for now */ - MPL_snprintf(charpid, sizeof(charpid), "%d",getpid()); - newargv[5] = charpid; - newargv[6] = NULL; - rc = execvp(newargv[0], (char **)newargv); - perror("PMII_singinit: execv failed"); - PMIU_printf(1, " This singleton init program attempted to access some feature\n"); - PMIU_printf(1, " for which process manager support was required, e.g. spawn or universe_size.\n"); - PMIU_printf(1, " But the necessary mpiexec is not in your path.\n"); - return PMI_FAIL; - } - else - { - char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE]; - char *p; - int connectStdio = 0; - - /* Allow one connection back from the created mpiexec program */ - PMI_fd = accept_one_connection(singinit_listen_sock); - if (PMI_fd < 0) { - PMIU_printf( 1, "Failed to establish singleton init connection\n" ); - return PMI_FAIL; - } - /* Execute the singleton init protocol */ - rc = PMIU_readline( PMI_fd, buf, PMIU_MAXLINE ); - PMIU_printf( PMI_debug_init, "Singinit: read %s\n", buf ); - - PMIU_parse_keyvals( buf ); - PMIU_getval( "cmd", cmd, PMIU_MAXLINE ); - if (strcmp( cmd, "singinit" ) != 0) { - PMIU_printf( 1, "unexpected command from PM: %s\n", cmd ); - return PMI_FAIL; - } - p = PMIU_getval( "authtype", cmd, PMIU_MAXLINE ); - if (p && strcmp( cmd, "none" ) != 0) { - PMIU_printf( 1, "unsupported authentication method %s\n", cmd ); - return PMI_FAIL; - } - /* p = PMIU_getval( "authstring", cmd, PMIU_MAXLINE ); */ - - /* If we're successful, send back our own singinit */ - rc = MPL_snprintf( buf, PMIU_MAXLINE, - "cmd=singinit pmi_version=%d pmi_subversion=%d stdio=yes authtype=none\n", - PMI_VERSION, PMI_SUBVERSION ); - if (rc < 0) { - return PMI_FAIL; - } - PMIU_printf( PMI_debug_init, "GetResponse with %s\n", buf ); - - rc = GetResponse( buf, "singinit_info", 0 ); - if (rc != 0) { - PMIU_printf( 1, "GetResponse failed\n" ); - return PMI_FAIL; - } - p = PMIU_getval( "versionok", cmd, PMIU_MAXLINE ); - if (p && strcmp( cmd, "yes" ) != 0) { - PMIU_printf( 1, "Process manager needs a different PMI version\n" ); - return PMI_FAIL; - } - p = PMIU_getval( "stdio", cmd, PMIU_MAXLINE ); - if (p && strcmp( cmd, "yes" ) == 0) { - PMIU_printf( PMI_debug_init, "PM agreed to connect stdio\n" ); - connectStdio = 1; - } - p = PMIU_getval( "kvsname", singinit_kvsname, sizeof(singinit_kvsname) ); - PMIU_printf( PMI_debug_init, "kvsname to use is %s\n", - singinit_kvsname ); - - if (connectStdio) { - PMIU_printf( PMI_debug_init, - "Accepting three connections for stdin, out, err\n" ); - stdin_sock = accept_one_connection(singinit_listen_sock); - dup2(stdin_sock, 0); - stdout_sock = accept_one_connection(singinit_listen_sock); - dup2(stdout_sock,1); - stderr_sock = accept_one_connection(singinit_listen_sock); - dup2(stderr_sock,2); - } - PMIU_printf( PMI_debug_init, "Done with singinit handshake\n" ); + perror("PMII_singinit: fork failed"); + exit(-1); + } else if (pid == 0) { + newargv[0] = "mpiexec"; + newargv[1] = "-pmi_args"; + newargv[2] = port_c; + /* FIXME: Use a valid hostname */ + newargv[3] = "default_interface"; /* default interface name, for now */ + newargv[4] = "default_key"; /* default authentication key, for now */ + MPL_snprintf(charpid, sizeof(charpid), "%d", getpid()); + newargv[5] = charpid; + newargv[6] = NULL; + rc = execvp(newargv[0], (char **) newargv); + perror("PMII_singinit: execv failed"); + PMIU_printf(1, " This singleton init program attempted to access some feature\n"); + PMIU_printf(1, + " for which process manager support was required, e.g. spawn or universe_size.\n"); + PMIU_printf(1, " But the necessary mpiexec is not in your path.\n"); + return PMI_FAIL; + } else { + char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE]; + char *p; + int connectStdio = 0; + + /* Allow one connection back from the created mpiexec program */ + PMI_fd = accept_one_connection(singinit_listen_sock); + if (PMI_fd < 0) { + PMIU_printf(1, "Failed to establish singleton init connection\n"); + return PMI_FAIL; + } + /* Execute the singleton init protocol */ + rc = PMIU_readline(PMI_fd, buf, PMIU_MAXLINE); + PMIU_printf(PMI_debug_init, "Singinit: read %s\n", buf); + + PMIU_parse_keyvals(buf); + PMIU_getval("cmd", cmd, PMIU_MAXLINE); + if (strcmp(cmd, "singinit") != 0) { + PMIU_printf(1, "unexpected command from PM: %s\n", cmd); + return PMI_FAIL; + } + p = PMIU_getval("authtype", cmd, PMIU_MAXLINE); + if (p && strcmp(cmd, "none") != 0) { + PMIU_printf(1, "unsupported authentication method %s\n", cmd); + return PMI_FAIL; + } + /* p = PMIU_getval("authstring", cmd, PMIU_MAXLINE); */ + + /* If we're successful, send back our own singinit */ + rc = MPL_snprintf(buf, PMIU_MAXLINE, + "cmd=singinit pmi_version=%d pmi_subversion=%d stdio=yes authtype=none\n", + PMI_VERSION, PMI_SUBVERSION); + if (rc < 0) { + return PMI_FAIL; + } + PMIU_printf(PMI_debug_init, "GetResponse with %s\n", buf); + + rc = GetResponse(buf, "singinit_info", 0); + if (rc != 0) { + PMIU_printf(1, "GetResponse failed\n"); + return PMI_FAIL; + } + p = PMIU_getval("versionok", cmd, PMIU_MAXLINE); + if (p && strcmp(cmd, "yes") != 0) { + PMIU_printf(1, "Process manager needs a different PMI version\n"); + return PMI_FAIL; + } + p = PMIU_getval("stdio", cmd, PMIU_MAXLINE); + if (p && strcmp(cmd, "yes") == 0) { + PMIU_printf(PMI_debug_init, "PM agreed to connect stdio\n"); + connectStdio = 1; + } + p = PMIU_getval("kvsname", singinit_kvsname, sizeof(singinit_kvsname)); + PMIU_printf(PMI_debug_init, "kvsname to use is %s\n", singinit_kvsname); + + if (connectStdio) { + PMIU_printf(PMI_debug_init, "Accepting three connections for stdin, out, err\n"); + stdin_sock = accept_one_connection(singinit_listen_sock); + dup2(stdin_sock, 0); + stdout_sock = accept_one_connection(singinit_listen_sock); + dup2(stdout_sock, 1); + stderr_sock = accept_one_connection(singinit_listen_sock); + dup2(stderr_sock, 2); + } + PMIU_printf(PMI_debug_init, "Done with singinit handshake\n"); } return PMI_SUCCESS; } @@ -1260,28 +1220,29 @@ static int PMIi_InitIfSingleton(void) int rc; static int firstcall = 1; - if (PMI_initialized != SINGLETON_INIT_BUT_NO_PM || !firstcall) return PMI_SUCCESS; + if (PMI_initialized != SINGLETON_INIT_BUT_NO_PM || !firstcall) + return PMI_SUCCESS; /* We only try to init as a singleton the first time */ firstcall = 0; - /* First, start (if necessary) an mpiexec, connect to it, - and start the singleton init handshake */ + /* First, start (if necessary) an mpiexec, connect to it, + * and start the singleton init handshake */ rc = PMII_singinit(); if (rc < 0) - return PMI_FAIL; - PMI_initialized = SINGLETON_INIT_WITH_PM; /* do this right away */ - PMI_size = 1; - PMI_rank = 0; - PMI_debug = 0; - PMI_spawned = 0; + return PMI_FAIL; + PMI_initialized = SINGLETON_INIT_WITH_PM; /* do this right away */ + PMI_size = 1; + PMI_rank = 0; + PMI_debug = 0; + PMI_spawned = 0; - PMII_getmaxes( &PMI_kvsname_max, &PMI_keylen_max, &PMI_vallen_max ); + PMII_getmaxes(&PMI_kvsname_max, &PMI_keylen_max, &PMI_vallen_max); - /* FIXME: We need to support a distinct kvsname for each - process group */ - PMI_KVS_Put( singinit_kvsname, cached_singinit_key, cached_singinit_val ); + /* FIXME: We need to support a distinct kvsname for each + * process group */ + PMI_KVS_Put(singinit_kvsname, cached_singinit_key, cached_singinit_val); return PMI_SUCCESS; } @@ -1289,101 +1250,94 @@ static int PMIi_InitIfSingleton(void) static int accept_one_connection(int list_sock) { int gotit, new_sock; - struct sockaddr_in from; + MPL_sockaddr_t addr; socklen_t len; - len = sizeof(from); + len = sizeof(addr); gotit = 0; - while ( ! gotit ) - { - new_sock = accept(list_sock, (struct sockaddr *)&from, &len); - if (new_sock == -1) - { - if (errno == EINTR) /* interrupted? If so, try again */ - continue; - else - { - PMIU_printf(1, "accept failed in accept_one_connection\n"); - exit(-1); - } - } - else - gotit = 1; + while (!gotit) { + new_sock = accept(list_sock, (struct sockaddr *) &addr, &len); + if (new_sock == -1) { + if (errno == EINTR) /* interrupted? If so, try again */ + continue; + else { + PMIU_printf(1, "accept failed in accept_one_connection\n"); + exit(-1); + } + } else + gotit = 1; } - return(new_sock); + return (new_sock); } #endif /* end USE_PMI_PORT */ -/* Get the FD to use for PMI operations. If a port is used, rather than - a pre-established FD (i.e., via pipe), this routine will handle the - initial handshake. +/* Get the FD to use for PMI operations. If a port is used, rather than + a pre-established FD (i.e., via pipe), this routine will handle the + initial handshake. */ -static int getPMIFD( int *notset ) +static int getPMIFD(int *notset) { char *p; /* Set the default */ PMI_fd = -1; - - p = getenv( "PMI_FD" ); + + p = getenv("PMI_FD"); if (p) { - PMI_fd = atoi( p ); - return PMI_SUCCESS; + PMI_fd = atoi(p); + return PMI_SUCCESS; } - #ifdef USE_PMI_PORT - p = getenv( "PMI_PORT" ); + p = getenv("PMI_PORT"); if (p) { - int portnum; - char hostname[MAXHOSTNAME+1]; - char *pn, *ph; - int id = 0; - - /* Connect to the indicated port (in format hostname:portnumber) - and get the fd for the socket */ - - /* Split p into host and port */ - pn = p; - ph = hostname; - while (*pn && *pn != ':' && (ph - hostname) < MAXHOSTNAME) { - *ph++ = *pn++; - } - *ph = 0; - - if (PMI_debug) { - DBG_PRINTF( ("Connecting to %s\n", p) ); - } - if (*pn == ':') { - portnum = atoi( pn+1 ); - /* FIXME: Check for valid integer after : */ - /* This routine only gets the fd to use to talk to - the process manager. The handshake below is used - to setup the initial values */ - PMI_fd = PMII_Connect_to_pm( hostname, portnum ); - if (PMI_fd < 0) { - PMIU_printf( 1, "Unable to connect to %s on %d\n", - hostname, portnum ); - return PMI_FAIL; - } - } - else { - PMIU_printf( 1, "unable to decode hostport from %s\n", p ); - return PMI_FAIL; - } - - /* We should first handshake to get size, rank, debug. */ - p = getenv( "PMI_ID" ); - if (p) { - id = atoi( p ); - /* PMII_Set_from_port sets up the values that are delivered - by enviroment variables when a separate port is not used */ - PMII_Set_from_port( PMI_fd, id ); - *notset = 0; - } - return PMI_SUCCESS; + int portnum; + char hostname[MAXHOSTNAME + 1]; + char *pn, *ph; + int id = 0; + + /* Connect to the indicated port (in format hostname:portnumber) + * and get the fd for the socket */ + + /* Split p into host and port */ + pn = p; + ph = hostname; + while (*pn && *pn != ':' && (ph - hostname) < MAXHOSTNAME) { + *ph++ = *pn++; + } + *ph = 0; + + if (PMI_debug) { + DBG_PRINTF(("Connecting to %s\n", p)); + } + if (*pn == ':') { + portnum = atoi(pn + 1); + /* FIXME: Check for valid integer after : */ + /* This routine only gets the fd to use to talk to + * the process manager. The handshake below is used + * to setup the initial values */ + PMI_fd = PMII_Connect_to_pm(hostname, portnum); + if (PMI_fd < 0) { + PMIU_printf(1, "Unable to connect to %s on %d\n", hostname, portnum); + return PMI_FAIL; + } + } else { + PMIU_printf(1, "unable to decode hostport from %s\n", p); + return PMI_FAIL; + } + + /* We should first handshake to get size, rank, debug. */ + p = getenv("PMI_ID"); + if (p) { + id = atoi(p); + /* PMII_Set_from_port sets up the values that are delivered + * by environment variables when a separate port is not used */ + PMII_Set_from_port(PMI_fd, id); + *notset = 0; + } + return PMI_SUCCESS; } #endif