"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "utils/sock/sock.c" between
hydra-3.3.1.tar.gz and hydra-3.3.2.tar.gz

About: Hydra (MPICH) is a process management system for starting parallel jobs. Hydra is designed to natively work with existing launcher daemons (such as ssh, rsh, fork), as well as natively integrate with resource management systems (such as slurm, pbs, sge).

sock.c  (hydra-3.3.1):sock.c  (hydra-3.3.2)
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
/* /*
* (C) 2008 by Argonne National Laboratory. * (C) 2008 by Argonne National Laboratory.
* See COPYRIGHT in top-level directory. * See COPYRIGHT in top-level directory.
*/ */
#include "hydra.h" #include "hydra.h"
#include "demux.h" #include "demux.h"
#include "mpl.h"
struct fwd_hash { struct fwd_hash {
int in; int in;
int out; int out;
char buf[HYD_TMPBUF_SIZE]; char buf[HYD_TMPBUF_SIZE];
int buf_offset; int buf_offset;
int buf_count; int buf_count;
struct fwd_hash *next; struct fwd_hash *next;
}; };
/* FIXME: redudant code with PMIServGetPort. Can we call PMIServGetPort here? */
HYD_status HYDU_sock_listen(int *listen_fd, char *port_range, uint16_t * port) HYD_status HYDU_sock_listen(int *listen_fd, char *port_range, uint16_t * port)
{ {
struct sockaddr_in sa; int ret;
int one = 1; int one = 1;
uint16_t low_port, high_port; uint16_t low_port, high_port;
char *port_str; char *port_str;
uint16_t i; uint16_t i;
HYD_status status = HYD_SUCCESS; HYD_status status = HYD_SUCCESS;
HYDU_FUNC_ENTER(); HYDU_FUNC_ENTER();
low_port = 0; low_port = 0;
high_port = 0; high_port = 0;
skipping to change at line 58 skipping to change at line 60
if (high_port < low_port) if (high_port < low_port)
HYDU_ERR_SETANDJUMP(status, HYD_INTERNAL_ERROR, "high port < low por t\n"); HYDU_ERR_SETANDJUMP(status, HYD_INTERNAL_ERROR, "high port < low por t\n");
} else { } else {
/* If port range is NULL, if a port is already provided, we /* If port range is NULL, if a port is already provided, we
* pick that. Otherwise, we search for an available port. */ * pick that. Otherwise, we search for an available port. */
low_port = *port; low_port = *port;
high_port = *port; high_port = *port;
} }
setup_socket: setup_socket:
*listen_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); *listen_fd = MPL_socket();
/* FIXME: duplicate with pm/hydra2/libhydra/sock/hydra_sock.c */
if (*listen_fd < 0) if (*listen_fd < 0)
HYDU_ERR_SETANDJUMP(status, HYD_SOCK_ERROR, "cannot open socket (%s)\n", HYDU_ERR_SETANDJUMP(status, HYD_SOCK_ERROR, "cannot open socket (%s)\n",
MPL_strerror(errno)); MPL_strerror(errno));
if (setsockopt(*listen_fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(int)) < 0) if (setsockopt(*listen_fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(int)) < 0)
HYDU_ERR_SETANDJUMP(status, HYD_SOCK_ERROR, "cannot set TCP_NODELAY\n"); HYDU_ERR_SETANDJUMP(status, HYD_SOCK_ERROR, "cannot set TCP_NODELAY\n");
/* The sockets standard does not guarantee that a successful /* The sockets standard does not guarantee that a successful
* return here means that this is set. However, REUSEADDR not * return here means that this is set. However, REUSEADDR not
* being set is not a fatal error, so we ignore that * being set is not a fatal error, so we ignore that
* case. However, we do check for error cases, which means that * case. However, we do check for error cases, which means that
* something bad has happened. */ * something bad has happened. */
if (setsockopt(*listen_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int)) < 0) if (setsockopt(*listen_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int)) < 0)
HYDU_ERR_SETANDJUMP(status, HYD_SOCK_ERROR, "cannot set SO_REUSEADDR\n") ; HYDU_ERR_SETANDJUMP(status, HYD_SOCK_ERROR, "cannot set SO_REUSEADDR\n") ;
for (i = low_port; i <= high_port; i++) { if (low_port == 0) {
memset((void *) &sa, 0, sizeof(struct sockaddr_in)); ret = MPL_listen_anyport(*listen_fd, port);
sa.sin_family = AF_INET; if (ret)
sa.sin_port = htons(i); HYDU_ERR_SETANDJUMP(status, HYD_SOCK_ERROR, "failed to bind to any p
sa.sin_addr.s_addr = INADDR_ANY; ort\n");
} else {
if (bind(*listen_fd, (struct sockaddr *) &sa, sizeof(struct sockaddr_in) ret = MPL_listen_portrange(*listen_fd, port, low_port, high_port);
) < 0) { if (ret == -2) {
/* If the address is in use, we should try the next HYDU_ERR_SETANDJUMP(status, HYD_SOCK_ERROR, "no port to bind\n");
* port. Otherwise, it's an error. */ } else if (ret < 0) {
if (errno != EADDRINUSE)
HYDU_ERR_SETANDJUMP(status, HYD_SOCK_ERROR, "bind error (%s)\n",
MPL_strerror(errno));
} else /* We got a port */
break;
}
*port = i;
if (*port > high_port)
HYDU_ERR_SETANDJUMP(status, HYD_SOCK_ERROR, "no port to bind\n");
if (listen(*listen_fd, SOMAXCONN) < 0) {
if (errno == EADDRINUSE) {
/* We need to close the socket and rebind to a new port */
close(*listen_fd);
goto setup_socket;
} else {
HYDU_ERR_SETANDJUMP(status, HYD_SOCK_ERROR, "listen error (%s)\n", M PL_strerror(errno)); HYDU_ERR_SETANDJUMP(status, HYD_SOCK_ERROR, "listen error (%s)\n", M PL_strerror(errno));
} }
/* We got a port */
} }
/* We asked for any port, so we need to find out which port we /* FIXME: the original code checks EADDRINUSE in both bind and listen. Is th
* actually got. */ ere a case EADDRINUSE slip through bind? If there is, we need somehow restore th
if (*port == 0) { e original code logic. */
socklen_t sinlen = sizeof(struct sockaddr_in);
if (getsockname(*listen_fd, (struct sockaddr *) &sa, &sinlen) < 0)
HYDU_ERR_SETANDJUMP(status, HYD_SOCK_ERROR, "getsockname error (%s)\
n",
MPL_strerror(errno));
*port = ntohs(sa.sin_port);
}
fn_exit: fn_exit:
HYDU_FUNC_EXIT(); HYDU_FUNC_EXIT();
return status; return status;
fn_fail: fn_fail:
goto fn_exit; goto fn_exit;
} }
HYD_status HYDU_sock_connect(const char *host, uint16_t port, int *fd, int retri es, HYD_status HYDU_sock_connect(const char *host, uint16_t port, int *fd, int retri es,
unsigned long delay) unsigned long delay)
{ {
struct hostent *ht; MPL_sockaddr_t addr;
struct sockaddr_in sa;
int one = 1, ret, retry_count; int one = 1, ret, retry_count;
HYD_status status = HYD_SUCCESS; HYD_status status = HYD_SUCCESS;
HYDU_FUNC_ENTER(); HYDU_FUNC_ENTER();
memset((char *) &sa, 0, sizeof(struct sockaddr_in)); ret = MPL_get_sockaddr(host, &addr);
sa.sin_family = AF_INET; if (ret)
sa.sin_port = htons(port); HYDU_ERR_SETANDJUMP(status, HYD_INVALID_PARAM, "unable to get host addre
ss for %s\n", host);
/* Get the remote host's IP address. Note that this is not
* thread-safe. Since we don't use threads right now, we don't
* worry about locking it. */
ht = gethostbyname(host);
if (ht == NULL)
HYDU_ERR_SETANDJUMP(status, HYD_INVALID_PARAM,
"unable to get host address for %s (%s)\n", host ? h
ost : "NULL",
HYDU_herror(h_errno));
memcpy(&sa.sin_addr, ht->h_addr_list[0], ht->h_length);
/* Create a socket and set the required options */ /* Create a socket and set the required options */
*fd = socket(AF_INET, SOCK_STREAM, 0); *fd = MPL_socket();
if (*fd < 0) if (*fd < 0)
HYDU_ERR_SETANDJUMP(status, HYD_SOCK_ERROR, "cannot open socket (%s)\n", HYDU_ERR_SETANDJUMP(status, HYD_SOCK_ERROR, "cannot open socket (%s)\n",
MPL_strerror(errno)); MPL_strerror(errno));
/* Not being able to connect is not an error in all cases. So we /* Not being able to connect is not an error in all cases. So we
* return an error, but only print a warning message. The upper * return an error, but only print a warning message. The upper
* layer can decide what to do with the return status. */ * layer can decide what to do with the return status. */
retry_count = 0; retry_count = 0;
do { do {
ret = connect(*fd, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)); ret = MPL_connect(*fd, &addr, port);
if (ret < 0 && (errno == ECONNREFUSED || errno == ETIMEDOUT)) { if (ret < 0 && (errno == ECONNREFUSED || errno == ETIMEDOUT)) {
/* connection error; increase retry count and delay */ /* connection error; increase retry count and delay */
retry_count++; retry_count++;
if (retry_count > retries) if (retry_count > retries)
break; break;
HYDU_delay(delay); HYDU_delay(delay);
} else } else
break; break;
} while (1); } while (1);
skipping to change at line 478 skipping to change at line 445
for (fwd_hash = fwd_hash_list; fwd_hash;) { for (fwd_hash = fwd_hash_list; fwd_hash;) {
tmp = fwd_hash->next; tmp = fwd_hash->next;
MPL_free(fwd_hash); MPL_free(fwd_hash);
fwd_hash = tmp; fwd_hash = tmp;
} }
} }
HYD_status HYDU_sock_get_iface_ip(char *iface, char **ip) HYD_status HYDU_sock_get_iface_ip(char *iface, char **ip)
{ {
HYD_status status = HYD_SUCCESS; HYD_status status = HYD_SUCCESS;
int ret;
#if defined(HAVE_GETIFADDRS) #if defined(HAVE_GETIFADDRS)
struct ifaddrs *ifaddr, *ifa; MPL_sockaddr_t addr;
char buf[MAX_HOSTNAME_LEN]; ret = MPL_get_sockaddr_iface(iface, &addr);
struct sockaddr_in *sa; if (ret)
/* Got the interface name; let's query for the IP address */
if (getifaddrs(&ifaddr) == -1)
HYDU_ERR_SETANDJUMP(status, HYD_INTERNAL_ERROR, "getifaddrs failed\n");
for (ifa = ifaddr; ifa; ifa = ifa->ifa_next)
if (!strcmp(ifa->ifa_name, iface) && (ifa->ifa_addr) &&
(ifa->ifa_addr->sa_family == AF_INET))
break;
if (!ifa)
HYDU_ERR_SETANDJUMP(status, HYD_INTERNAL_ERROR, "unable to find interfac e %s\n", iface); HYDU_ERR_SETANDJUMP(status, HYD_INTERNAL_ERROR, "unable to find interfac e %s\n", iface);
sa = (struct sockaddr_in *) ifa->ifa_addr; char buf[MAX_HOSTNAME_LEN];
#if defined HAVE_INET_NTOP ret = MPL_sockaddr_to_str(&addr, buf, MAX_HOSTNAME_LEN);
(*ip) = MPL_strdup((char *) (*ip) = MPL_strdup(buf);
inet_ntop(AF_INET, (const void *) &(sa->sin_addr), buf, M
AX_HOSTNAME_LEN));
#else
(*ip) = NULL;
#endif /* HAVE_INET_NTOP */
if (!*ip)
HYDU_ERR_SETANDJUMP(status, HYD_INTERNAL_ERROR,
"unable to find IP for interface %s\n", iface);
freeifaddrs(ifaddr);
#else #else
/* For now just disable interface selection when getifaddrs isn't /* For now just disable interface selection when getifaddrs isn't
* available, such as on AIX. In the future we can implement in MPL * available, such as on AIX. In the future we can implement in MPL
* something along the lines of MPIDI_GetIPInterface from tcp_getip.c in * something along the lines of MPIDI_GetIPInterface from tcp_getip.c in
* nemesis. */ * nemesis. */
HYDU_ERR_SETANDJUMP(status, HYD_INTERNAL_ERROR, HYDU_ERR_SETANDJUMP(status, HYD_INTERNAL_ERROR,
"interface selection not supported on this platform\n"); "interface selection not supported on this platform\n");
#endif #endif
fn_exit: fn_exit:
 End of changes. 14 change blocks. 
85 lines changed or deleted 33 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)