2004-09-08 18:03:05 +00:00
|
|
|
/*
|
2005-11-05 19:57:48 +00:00
|
|
|
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
|
|
|
* University Research and Technology
|
|
|
|
* Corporation. All rights reserved.
|
2006-08-23 03:32:36 +00:00
|
|
|
* Copyright (c) 2004-2006 The University of Tennessee and The University
|
2005-11-05 19:57:48 +00:00
|
|
|
* of Tennessee Research Foundation. All rights
|
|
|
|
* reserved.
|
2004-11-28 20:09:25 +00:00
|
|
|
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
|
|
|
* University of Stuttgart. All rights reserved.
|
2005-03-24 12:43:37 +00:00
|
|
|
* Copyright (c) 2004-2005 The Regents of the University of California.
|
|
|
|
* All rights reserved.
|
2010-02-22 15:05:09 +00:00
|
|
|
* Copyright (c) 2006-2010 Cisco Systems, Inc. All rights reserved.
|
2012-04-06 14:23:13 +00:00
|
|
|
* Copyright (c) 2012 Los Alamos National Security, LLC.
|
|
|
|
* All rights reserved.
|
2004-11-22 01:38:40 +00:00
|
|
|
* $COPYRIGHT$
|
|
|
|
*
|
|
|
|
* Additional copyrights may follow
|
|
|
|
*
|
2004-09-08 18:03:05 +00:00
|
|
|
* $HEADER$
|
2006-03-11 03:09:24 +00:00
|
|
|
*
|
|
|
|
* In windows, many of the socket functions return an EWOULDBLOCK
|
|
|
|
* instead of \ things like EAGAIN, EINPROGRESS, etc. It has been
|
|
|
|
* verified that this will \ not conflict with other error codes that
|
|
|
|
* are returned by these functions \ under UNIX/Linux environments
|
2004-09-08 18:03:05 +00:00
|
|
|
*/
|
2006-03-11 03:09:24 +00:00
|
|
|
|
2006-02-12 01:33:29 +00:00
|
|
|
#include "orte_config.h"
|
2008-02-28 01:57:57 +00:00
|
|
|
#include "orte/types.h"
|
|
|
|
|
2005-05-05 16:31:40 +00:00
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
#include <fcntl.h>
|
|
|
|
#ifdef HAVE_SYS_UIO_H
|
|
|
|
#include <sys/uio.h>
|
|
|
|
#endif
|
2007-07-10 03:46:57 +00:00
|
|
|
#ifdef HAVE_NET_UIO_H
|
|
|
|
#include <net/uio.h>
|
|
|
|
#endif
|
2005-05-05 16:31:40 +00:00
|
|
|
#ifdef HAVE_SYS_TYPES_H
|
|
|
|
#include <sys/types.h>
|
|
|
|
#endif
|
2010-02-22 15:05:09 +00:00
|
|
|
#ifdef HAVE_SYS_SOCKET_H
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#endif
|
2005-05-05 16:31:40 +00:00
|
|
|
#ifdef HAVE_NETINET_IN_H
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_ARPA_INET_H
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_NETINET_TCP_H
|
|
|
|
#include <netinet/tcp.h>
|
|
|
|
#endif
|
2006-07-18 09:07:53 +00:00
|
|
|
#ifndef __WINDOWS__
|
|
|
|
#include <signal.h>
|
|
|
|
#endif
|
2010-02-22 15:05:09 +00:00
|
|
|
|
Update libevent to the 2.0 series, currently at 2.0.7rc. We will update to their final release when it becomes available. Currently known errors exist in unused portions of the libevent code. This revision passes the IBM test suite on a Linux machine and on a standalone Mac.
This is a fairly intrusive change, but outside of the moving of opal/event to opal/mca/event, the only changes involved (a) changing all calls to opal_event functions to reflect the new framework instead, and (b) ensuring that all opal_event_t objects are properly constructed since they are now true opal_objects.
Note: Shiqing has just returned from vacation and has not yet had a chance to complete the Windows integration. Thus, this commit almost certainly breaks Windows support on the trunk. However, I want this to have a chance to soak for as long as possible before I become less available a week from today (going to be at a class for 5 days, and thus will only be sparingly available) so we can find and fix any problems.
Biggest change is moving the libevent code from opal/event to a new opal/mca/event framework. This was done to make it much easier to update libevent in the future. New versions can be inserted as a new component and tested in parallel with the current version until validated, then we can remove the earlier version if we so choose. This is a statically built framework ala installdirs, so only one component will build at a time. There is no selection logic - the sole compiled component simply loads its function pointers into the opal_event struct.
I have gone thru the code base and converted all the libevent calls I could find. However, I cannot compile nor test every environment. It is therefore quite likely that errors remain in the system. Please keep an eye open for two things:
1. compile-time errors: these will be obvious as calls to the old functions (e.g., opal_evtimer_new) must be replaced by the new framework APIs (e.g., opal_event.evtimer_new)
2. run-time errors: these will likely show up as segfaults due to missing constructors on opal_event_t objects. It appears that it became a typical practice for people to "init" an opal_event_t by simply using memset to zero it out. This will no longer work - you must either OBJ_NEW or OBJ_CONSTRUCT an opal_event_t. I tried to catch these cases, but may have missed some. Believe me, you'll know when you hit it.
There is also the issue of the new libevent "no recursion" behavior. As I described on a recent email, we will have to discuss this and figure out what, if anything, we need to do.
This commit was SVN r23925.
2010-10-24 18:35:54 +00:00
|
|
|
#include "opal/mca/event/event.h"
|
2010-02-22 15:05:09 +00:00
|
|
|
#include "opal/opal_socket_errno.h"
|
Bring over the update to terminate orteds that are generated by a dynamic spawn such as comm_spawn. This introduces the concept of a job "family" - i.e., jobs that have a parent/child relationship. Comm_spawn'ed jobs have a parent (the one that spawned them). We track that relationship throughout the lineage - i.e., if a comm_spawned job in turn calls comm_spawn, then it has a parent (the one that spawned it) and a "root" job (the original job that started things).
Accordingly, there are new APIs to the name service to support the ability to get a job's parent, root, immediate children, and all its descendants. In addition, the terminate_job, terminate_orted, and signal_job APIs for the PLS have been modified to accept attributes that define the extent of their actions. For example, doing a "terminate_job" with an attribute of ORTE_NS_INCLUDE_DESCENDANTS will terminate the given jobid AND all jobs that descended from it.
I have tested this capability on a MacBook under rsh, Odin under SLURM, and LANL's Flash (bproc). It worked successfully on non-MPI jobs (both simple and including a spawn), and MPI jobs (again, both simple and with a spawn).
This commit was SVN r12597.
2006-11-14 19:34:59 +00:00
|
|
|
|
2008-02-28 01:57:57 +00:00
|
|
|
#include "orte/util/name_fns.h"
|
|
|
|
#include "orte/runtime/orte_globals.h"
|
Bring over the update to terminate orteds that are generated by a dynamic spawn such as comm_spawn. This introduces the concept of a job "family" - i.e., jobs that have a parent/child relationship. Comm_spawn'ed jobs have a parent (the one that spawned them). We track that relationship throughout the lineage - i.e., if a comm_spawned job in turn calls comm_spawn, then it has a parent (the one that spawned it) and a "root" job (the original job that started things).
Accordingly, there are new APIs to the name service to support the ability to get a job's parent, root, immediate children, and all its descendants. In addition, the terminate_job, terminate_orted, and signal_job APIs for the PLS have been modified to accept attributes that define the extent of their actions. For example, doing a "terminate_job" with an attribute of ORTE_NS_INCLUDE_DESCENDANTS will terminate the given jobid AND all jobs that descended from it.
I have tested this capability on a MacBook under rsh, Odin under SLURM, and LANL's Flash (bproc). It worked successfully on non-MPI jobs (both simple and including a spawn), and MPI jobs (again, both simple and with a spawn).
This commit was SVN r12597.
2006-11-14 19:34:59 +00:00
|
|
|
|
2006-02-12 01:33:29 +00:00
|
|
|
#include "orte/mca/oob/tcp/oob_tcp.h"
|
2004-09-08 18:03:05 +00:00
|
|
|
|
2006-07-17 21:15:56 +00:00
|
|
|
/*
|
|
|
|
* Local functions
|
|
|
|
*/
|
|
|
|
static void noop(int fd, short event, void *arg);
|
2005-05-05 16:31:40 +00:00
|
|
|
|
2004-09-08 18:03:05 +00:00
|
|
|
/*
|
|
|
|
* Ping a peer to see if it is alive.
|
|
|
|
*
|
|
|
|
* @param peer (IN) Opaque name of peer process.
|
|
|
|
* @param tv (IN) Timeout to wait for a response.
|
|
|
|
* @return OMPI error code (<0) on error number of bytes actually sent.
|
|
|
|
*/
|
|
|
|
|
2007-07-20 01:34:02 +00:00
|
|
|
int
|
|
|
|
mca_oob_tcp_ping(const orte_process_name_t* name,
|
|
|
|
const char* uri,
|
|
|
|
const struct timeval *timeout)
|
2004-09-08 18:03:05 +00:00
|
|
|
{
|
2005-05-05 16:31:40 +00:00
|
|
|
int sd, flags, rc;
|
2007-07-20 01:34:02 +00:00
|
|
|
struct sockaddr_storage inaddr;
|
2005-05-05 16:31:40 +00:00
|
|
|
fd_set fdset;
|
|
|
|
mca_oob_tcp_hdr_t hdr;
|
2004-09-08 18:03:05 +00:00
|
|
|
struct timeval tv;
|
2006-08-23 03:32:36 +00:00
|
|
|
struct iovec iov;
|
2006-07-17 21:15:56 +00:00
|
|
|
#ifndef __WINDOWS__
|
2012-04-06 14:23:13 +00:00
|
|
|
opal_event_t *sigpipe_handler;
|
2006-07-17 21:15:56 +00:00
|
|
|
#endif
|
2007-07-20 01:34:02 +00:00
|
|
|
socklen_t addrlen;
|
2004-09-08 18:03:05 +00:00
|
|
|
|
2005-05-05 16:31:40 +00:00
|
|
|
/* parse uri string */
|
2007-07-20 01:34:02 +00:00
|
|
|
if(ORTE_SUCCESS != (rc = mca_oob_tcp_parse_uri(uri, (struct sockaddr*) &inaddr))) {
|
2008-06-09 14:53:58 +00:00
|
|
|
opal_output(0,
|
2007-07-20 02:34:29 +00:00
|
|
|
"%s-%s mca_oob_tcp_ping: invalid uri: %s\n",
|
2009-03-05 21:50:47 +00:00
|
|
|
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
|
|
|
|
ORTE_NAME_PRINT(name),
|
2005-05-05 16:31:40 +00:00
|
|
|
uri);
|
|
|
|
return rc;
|
2004-09-08 18:03:05 +00:00
|
|
|
}
|
|
|
|
|
2005-05-05 16:31:40 +00:00
|
|
|
/* create socket */
|
2007-07-20 01:34:02 +00:00
|
|
|
sd = socket(inaddr.ss_family, SOCK_STREAM, 0);
|
2005-05-05 16:31:40 +00:00
|
|
|
if (sd < 0) {
|
2008-06-09 14:53:58 +00:00
|
|
|
opal_output(0,
|
2007-07-20 02:34:29 +00:00
|
|
|
"%s-%s mca_oob_tcp_ping: socket() failed: %s (%d)\n",
|
2009-03-05 21:50:47 +00:00
|
|
|
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
|
|
|
|
ORTE_NAME_PRINT(name),
|
2006-12-14 18:20:43 +00:00
|
|
|
strerror(opal_socket_errno),
|
2006-08-14 20:14:44 +00:00
|
|
|
opal_socket_errno);
|
2006-02-12 01:33:29 +00:00
|
|
|
return ORTE_ERR_UNREACH;
|
2005-05-05 16:31:40 +00:00
|
|
|
}
|
2004-09-08 18:03:05 +00:00
|
|
|
|
2005-05-05 16:31:40 +00:00
|
|
|
/* setup the socket as non-blocking */
|
|
|
|
if((flags = fcntl(sd, F_GETFL, 0)) < 0) {
|
2008-06-09 14:53:58 +00:00
|
|
|
opal_output(0, "%s-%s mca_oob_tcp_ping: fcntl(F_GETFL) failed: %s (%d)\n",
|
2009-03-05 21:50:47 +00:00
|
|
|
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
|
|
|
|
ORTE_NAME_PRINT(name),
|
2006-12-14 18:20:43 +00:00
|
|
|
strerror(opal_socket_errno),
|
2006-08-14 20:14:44 +00:00
|
|
|
opal_socket_errno);
|
2005-03-14 20:57:21 +00:00
|
|
|
} else {
|
2005-05-05 16:31:40 +00:00
|
|
|
flags |= O_NONBLOCK;
|
|
|
|
if(fcntl(sd, F_SETFL, flags) < 0) {
|
2008-06-09 14:53:58 +00:00
|
|
|
opal_output(0, "%s-%s mca_oob_tcp_ping: fcntl(F_SETFL) failed: %s (%d)\n",
|
2009-03-05 21:50:47 +00:00
|
|
|
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
|
|
|
|
ORTE_NAME_PRINT(name),
|
2006-12-14 18:20:43 +00:00
|
|
|
strerror(opal_socket_errno),
|
2006-08-14 20:14:44 +00:00
|
|
|
opal_socket_errno);
|
2005-05-05 16:31:40 +00:00
|
|
|
}
|
2005-03-14 20:57:21 +00:00
|
|
|
}
|
2004-09-08 18:03:05 +00:00
|
|
|
|
2007-07-20 01:34:02 +00:00
|
|
|
switch (inaddr.ss_family) {
|
|
|
|
case AF_INET:
|
|
|
|
addrlen = sizeof(struct sockaddr_in);
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
addrlen = sizeof(struct sockaddr_in6);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
addrlen = 0;
|
|
|
|
}
|
|
|
|
|
2005-05-05 16:31:40 +00:00
|
|
|
/* start the connect - will likely fail with EINPROGRESS */
|
|
|
|
FD_ZERO(&fdset);
|
2007-07-20 01:34:02 +00:00
|
|
|
if(connect(sd, (struct sockaddr*)&inaddr, addrlen) < 0) {
|
2005-05-05 16:31:40 +00:00
|
|
|
/* connect failed? */
|
2006-08-14 20:14:44 +00:00
|
|
|
if(opal_socket_errno != EINPROGRESS && opal_socket_errno != EWOULDBLOCK) {
|
2008-06-09 14:53:58 +00:00
|
|
|
opal_output(0, "%s-%s mca_oob_tcp_ping: connect failed: %s (%d)\n",
|
2009-03-05 21:50:47 +00:00
|
|
|
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
|
|
|
|
ORTE_NAME_PRINT(name),
|
2007-07-20 01:34:02 +00:00
|
|
|
strerror(opal_socket_errno),
|
|
|
|
opal_socket_errno);
|
2006-08-23 03:32:36 +00:00
|
|
|
CLOSE_THE_SOCKET(sd);
|
2006-02-12 01:33:29 +00:00
|
|
|
return ORTE_ERR_UNREACH;
|
2005-05-05 16:31:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* select with timeout to wait for connect to complete */
|
|
|
|
FD_SET(sd, &fdset);
|
|
|
|
tv = *timeout;
|
|
|
|
rc = select(sd+1, NULL, &fdset, NULL, &tv);
|
|
|
|
if(rc <= 0) {
|
2006-08-23 03:32:36 +00:00
|
|
|
CLOSE_THE_SOCKET(sd);
|
2006-02-12 01:33:29 +00:00
|
|
|
return ORTE_ERR_UNREACH;
|
2005-05-05 16:31:40 +00:00
|
|
|
}
|
2004-09-08 18:03:05 +00:00
|
|
|
}
|
|
|
|
|
2005-05-05 16:31:40 +00:00
|
|
|
/* set socket back to blocking */
|
|
|
|
flags &= ~O_NONBLOCK;
|
|
|
|
if(fcntl(sd, F_SETFL, flags) < 0) {
|
2008-06-09 14:53:58 +00:00
|
|
|
opal_output(0, "%s-%s mca_oob_tcp_ping: fcntl(F_SETFL) failed: %s (%d)\n",
|
2009-03-05 21:50:47 +00:00
|
|
|
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
|
|
|
|
ORTE_NAME_PRINT(name),
|
2006-12-14 18:20:43 +00:00
|
|
|
strerror(opal_socket_errno),
|
2006-08-14 20:14:44 +00:00
|
|
|
opal_socket_errno);
|
2004-09-08 18:03:05 +00:00
|
|
|
}
|
2005-05-05 16:31:40 +00:00
|
|
|
|
|
|
|
/* send a probe message */
|
|
|
|
memset(&hdr, 0, sizeof(hdr));
|
2008-02-28 01:57:57 +00:00
|
|
|
hdr.msg_src = *ORTE_PROC_MY_NAME;
|
|
|
|
|
2005-05-05 16:31:40 +00:00
|
|
|
hdr.msg_dst = *name;
|
|
|
|
hdr.msg_type = MCA_OOB_TCP_PROBE;
|
2005-05-18 15:31:23 +00:00
|
|
|
MCA_OOB_TCP_HDR_HTON(&hdr);
|
2006-07-17 21:15:56 +00:00
|
|
|
|
|
|
|
#ifndef __WINDOWS__
|
|
|
|
/* Ignore SIGPIPE in the write -- determine success or failure in
|
|
|
|
the ping by looking at the return code from write() */
|
2012-04-06 14:23:13 +00:00
|
|
|
sigpipe_handler = opal_event_alloc();
|
|
|
|
opal_event_signal_set(orte_event_base, sigpipe_handler, SIGPIPE,
|
|
|
|
noop, sigpipe_handler);
|
|
|
|
opal_event_signal_add(sigpipe_handler, NULL);
|
2006-07-17 21:15:56 +00:00
|
|
|
#endif
|
2006-08-23 03:32:36 +00:00
|
|
|
/* Do the write and see what happens. Use the writev version just to
|
|
|
|
* make Windows happy as there the write function is limitted to
|
|
|
|
* file operations.
|
|
|
|
*/
|
|
|
|
iov.iov_base = (IOVBASE_TYPE*)&hdr;
|
|
|
|
iov.iov_len = sizeof(hdr);
|
|
|
|
rc = writev(sd, &iov, 1 );
|
2006-07-17 21:15:56 +00:00
|
|
|
#ifndef __WINDOWS__
|
|
|
|
/* Now de-register the handler */
|
2012-04-06 14:23:13 +00:00
|
|
|
opal_event_free(sigpipe_handler);
|
2006-07-17 21:15:56 +00:00
|
|
|
#endif
|
|
|
|
if (rc != sizeof(hdr)) {
|
2006-08-23 03:32:36 +00:00
|
|
|
CLOSE_THE_SOCKET(sd);
|
2006-02-12 01:33:29 +00:00
|
|
|
return ORTE_ERR_UNREACH;
|
2005-05-05 16:31:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* select with timeout to wait for response */
|
|
|
|
FD_SET(sd, &fdset);
|
|
|
|
tv = *timeout;
|
|
|
|
rc = select(sd+1, &fdset, NULL, NULL, &tv);
|
|
|
|
if(rc <= 0) {
|
2006-08-23 03:32:36 +00:00
|
|
|
CLOSE_THE_SOCKET(sd);
|
2006-02-12 01:33:29 +00:00
|
|
|
return ORTE_ERR_UNREACH;
|
2005-05-05 16:31:40 +00:00
|
|
|
}
|
|
|
|
if((rc = read(sd, &hdr, sizeof(hdr))) != sizeof(hdr)) {
|
2006-08-23 03:32:36 +00:00
|
|
|
CLOSE_THE_SOCKET(sd);
|
2006-02-12 01:33:29 +00:00
|
|
|
return ORTE_ERR_UNREACH;
|
2005-05-05 16:31:40 +00:00
|
|
|
}
|
2005-05-18 15:31:23 +00:00
|
|
|
MCA_OOB_TCP_HDR_NTOH(&hdr);
|
2005-05-18 15:32:05 +00:00
|
|
|
if(hdr.msg_type != MCA_OOB_TCP_PROBE) {
|
2006-08-23 03:32:36 +00:00
|
|
|
CLOSE_THE_SOCKET(sd);
|
2006-02-12 01:33:29 +00:00
|
|
|
return ORTE_ERR_UNREACH;
|
2005-05-18 15:31:23 +00:00
|
|
|
}
|
2006-08-23 03:32:36 +00:00
|
|
|
CLOSE_THE_SOCKET(sd);
|
2006-02-12 01:33:29 +00:00
|
|
|
return ORTE_SUCCESS;
|
2004-09-08 18:03:05 +00:00
|
|
|
}
|
|
|
|
|
2005-05-05 16:31:40 +00:00
|
|
|
|
2006-07-17 21:15:56 +00:00
|
|
|
static void noop(int fd, short event, void *arg)
|
|
|
|
{
|
2012-04-06 14:23:13 +00:00
|
|
|
opal_event_t *ev = (opal_event_t*)arg;
|
|
|
|
|
|
|
|
/* return the event */
|
|
|
|
opal_event_free(ev);
|
2006-07-17 21:15:56 +00:00
|
|
|
}
|