root/orte/mca/odls/alps/odls_alps_module.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. odls_alps_kill_local
  2. orte_odls_alps_kill_local_procs
  3. set_handler_alps
  4. write_help_msg
  5. send_error_show_help
  6. close_open_file_descriptors
  7. do_child
  8. do_parent
  9. odls_alps_fork_local_proc
  10. orte_odls_alps_launch_local_procs
  11. send_signal
  12. orte_odls_alps_signal_local_procs
  13. orte_odls_alps_restart_proc

   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
   2 /*
   3  * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
   4  *                         University Research and Technology
   5  *                         Corporation.  All rights reserved.
   6  * Copyright (c) 2004-2008 The University of Tennessee and The University
   7  *                         of Tennessee Research Foundation.  All rights
   8  *                         reserved.
   9  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
  10  *                         University of Stuttgart.  All rights reserved.
  11  * Copyright (c) 2004-2005 The Regents of the University of California.
  12  *                         All rights reserved.
  13  * Copyright (c) 2007-2010 Oracle and/or its affiliates.  All rights reserved.
  14  * Copyright (c) 2007      Evergrid, Inc. All rights reserved.
  15  * Copyright (c) 2008-2017 Cisco Systems, Inc.  All rights reserved
  16  * Copyright (c) 2010      IBM Corporation.  All rights reserved.
  17  * Copyright (c) 2011-2018 Los Alamos National Security, LLC.  All rights
  18  *                         reserved.
  19  * Copyright (c) 2013-2017 Intel, Inc.  All rights reserved.
  20  * Copyright (c) 2017      Rutgers, The State University of New Jersey.
  21  *                         All rights reserved.
  22  * Copyright (c) 2017      Research Organization for Information Science
  23  *                         and Technology (RIST). All rights reserved.
  24  *
  25  * $COPYRIGHT$
  26  *
  27  * Additional copyrights may follow
  28  *
  29  * $HEADER$
  30  */
  31 
  32 /*
  33  * There is a complicated sequence of events that occurs when the
  34  * parent forks a child process that is intended to launch the target
  35  * executable.
  36  *
  37  * Before the child process exec's the target executable, it might tri
  38  * to set the affinity of that new child process according to a
  39  * complex series of rules.  This binding may fail in a myriad of
  40  * different ways.  A lot of this code deals with reporting that error
  41  * occurately to the end user.  This is a complex task in itself
  42  * because the child process is not "really" an ORTE process -- all
  43  * error reporting must be proxied up to the parent who can use normal
  44  * ORTE error reporting mechanisms.
  45  *
  46  * Here's a high-level description of what is occurring in this file:
  47  *
  48  * - parent opens a pipe
  49  * - parent forks a child
  50  * - parent blocks reading on the pipe: the pipe will either close
  51  *   (indicating that the child successfully exec'ed) or the child will
  52  *   write some proxied error data up the pipe
  53  *
  54  * - the child tries to set affinity and do other housekeeping in
  55  *   preparation of exec'ing the target executable
  56  * - if the child fails anywhere along the way, it sends a message up
  57  *   the pipe to the parent indicating what happened -- including a
  58  *   rendered error message detailing the problem (i.e., human-readable).
  59  * - it is important that the child renders the error message: there
  60  *   are so many errors that are possible that the child is really the
  61  *   only entity that has enough information to make an accuate error string
  62  *   to report back to the user.
  63  * - the parent reads this message + rendered string in and uses ORTE
  64  *   reporting mechanisms to display it to the user
  65  * - if the problem was only a warning, the child continues processing
  66  *   (potentially eventually exec'ing the target executable).
  67  * - if the problem was an error, the child exits and the parent
  68  *   handles the death of the child as appropriate (i.e., this ODLS
  69  *   simply reports the error -- other things decide what to do).
  70  */
  71 
  72 #include "orte_config.h"
  73 #include "orte/constants.h"
  74 #include "orte/types.h"
  75 
  76 #include <string.h>
  77 #include <stdlib.h>
  78 #ifdef HAVE_UNISTD_H
  79 #include <unistd.h>
  80 #endif
  81 #include <errno.h>
  82 #ifdef HAVE_SYS_TYPES_H
  83 #include <sys/types.h>
  84 #endif
  85 #ifdef HAVE_SYS_WAIT_H
  86 #include <sys/wait.h>
  87 #endif
  88 #include <signal.h>
  89 #ifdef HAVE_FCNTL_H
  90 #include <fcntl.h>
  91 #endif
  92 #ifdef HAVE_SYS_TIME_H
  93 #include <sys/time.h>
  94 #endif
  95 #ifdef HAVE_SYS_PARAM_H
  96 #include <sys/param.h>
  97 #endif
  98 #ifdef HAVE_NETDB_H
  99 #include <netdb.h>
 100 #endif
 101 #include <stdlib.h>
 102 #ifdef HAVE_SYS_STAT_H
 103 #include <sys/stat.h>
 104 #endif  /* HAVE_SYS_STAT_H */
 105 #include <stdarg.h>
 106 #ifdef HAVE_SYS_SELECT_H
 107 #include <sys/select.h>
 108 #endif
 109 #ifdef HAVE_DIRENT_H
 110 #include <dirent.h>
 111 #endif
 112 
 113 #include <ctype.h>
 114 
 115 #include "opal/mca/hwloc/hwloc-internal.h"
 116 #include "opal/mca/hwloc/base/base.h"
 117 #include "opal/class/opal_pointer_array.h"
 118 #include "opal/util/opal_environ.h"
 119 #include "opal/util/show_help.h"
 120 #include "opal/util/sys_limits.h"
 121 #include "opal/util/fd.h"
 122 
 123 #include "orte/util/show_help.h"
 124 #include "orte/runtime/orte_wait.h"
 125 #include "orte/runtime/orte_globals.h"
 126 #include "orte/mca/errmgr/errmgr.h"
 127 #include "orte/mca/ess/ess.h"
 128 #include "orte/mca/iof/base/iof_base_setup.h"
 129 #include "orte/mca/plm/plm.h"
 130 #include "orte/mca/rtc/rtc.h"
 131 #include "orte/util/name_fns.h"
 132 
 133 #include "orte/mca/odls/base/base.h"
 134 #include "orte/mca/odls/base/odls_private.h"
 135 #include "orte/mca/odls/alps/odls_alps.h"
 136 #include "orte/orted/pmix/pmix_server.h"
 137 
 138 /*
 139  * Module functions (function pointers used in a struct)
 140  */
 141 static int orte_odls_alps_launch_local_procs(opal_buffer_t *data);
 142 static int orte_odls_alps_kill_local_procs(opal_pointer_array_t *procs);
 143 static int orte_odls_alps_signal_local_procs(const orte_process_name_t *proc, int32_t signal);
 144 static int orte_odls_alps_restart_proc(orte_proc_t *child);
 145 
 146 /*
 147  * Explicitly declared functions so that we can get the noreturn
 148  * attribute registered with the compiler.
 149  */
 150 static void send_error_show_help(int fd, int exit_status,
 151                                  const char *file, const char *topic, ...)
 152     __opal_attribute_noreturn__;
 153 static int do_child(orte_odls_spawn_caddy_t *cd, int write_fd)
 154     __opal_attribute_noreturn__;
 155 
 156 
 157 /*
 158  * Module
 159  */
 160 orte_odls_base_module_t orte_odls_alps_module = {
 161     orte_odls_base_default_get_add_procs_data,
 162     orte_odls_alps_launch_local_procs,
 163     orte_odls_alps_kill_local_procs,
 164     orte_odls_alps_signal_local_procs,
 165     orte_odls_alps_restart_proc
 166 };
 167 
 168 
 169 static int odls_alps_kill_local(pid_t pid, int signum)
 170 {
 171     pid_t pgrp;
 172 
 173 #if HAVE_SETPGID
 174     pgrp = getpgid(pid);
 175     if (-1 != pgrp) {
 176         /* target the lead process of the process
 177          * group so we ensure that the signal is
 178          * seen by all members of that group. This
 179          * ensures that the signal is seen by any
 180          * child processes our child may have
 181          * started
 182          */
 183         pid = pgrp;
 184     }
 185 #endif
 186     if (0 != kill(pid, signum)) {
 187         if (ESRCH != errno) {
 188             OPAL_OUTPUT_VERBOSE((2, orte_odls_base_framework.framework_output,
 189                                  "%s odls:alps:SENT KILL %d TO PID %d GOT ERRNO %d",
 190                                  ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), signum, (int)pid, errno));
 191             return errno;
 192         }
 193     }
 194     OPAL_OUTPUT_VERBOSE((2, orte_odls_base_framework.framework_output,
 195                          "%s odls:alps:SENT KILL %d TO PID %d SUCCESS",
 196                          ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), signum, (int)pid));
 197     return 0;
 198 }
 199 
 200 int orte_odls_alps_kill_local_procs(opal_pointer_array_t *procs)
 201 {
 202     int rc;
 203 
 204     if (ORTE_SUCCESS != (rc = orte_odls_base_default_kill_local_procs(procs,
 205                                                 odls_alps_kill_local))) {
 206         ORTE_ERROR_LOG(rc);
 207         return rc;
 208     }
 209     return ORTE_SUCCESS;
 210 }
 211 
 212 
 213 static void set_handler_alps(int sig)
 214 {
 215     struct sigaction act;
 216 
 217     act.sa_handler = SIG_DFL;
 218     act.sa_flags = 0;
 219     sigemptyset(&act.sa_mask);
 220 
 221     sigaction(sig, &act, (struct sigaction *)0);
 222 }
 223 
 224 /*
 225  * Internal function to write a rendered show_help message back up the
 226  * pipe to the waiting parent.
 227  */
 228 static int write_help_msg(int fd, orte_odls_pipe_err_msg_t *msg, const char *file,
 229                           const char *topic, va_list ap)
 230 {
 231     int ret;
 232     char *str;
 233 
 234     if (NULL == file || NULL == topic) {
 235         return OPAL_ERR_BAD_PARAM;
 236     }
 237 
 238     str = opal_show_help_vstring(file, topic, true, ap);
 239 
 240     msg->file_str_len = (int) strlen(file);
 241     if (msg->file_str_len > ORTE_ODLS_MAX_FILE_LEN) {
 242         ORTE_ERROR_LOG(ORTE_ERR_BAD_PARAM);
 243         return ORTE_ERR_BAD_PARAM;
 244     }
 245     msg->topic_str_len = (int) strlen(topic);
 246     if (msg->topic_str_len > ORTE_ODLS_MAX_TOPIC_LEN) {
 247         ORTE_ERROR_LOG(ORTE_ERR_BAD_PARAM);
 248         return ORTE_ERR_BAD_PARAM;
 249     }
 250     msg->msg_str_len = (int) strlen(str);
 251 
 252     /* Only keep writing if each write() succeeds */
 253     if (OPAL_SUCCESS != (ret = opal_fd_write(fd, sizeof(*msg), msg))) {
 254         goto out;
 255     }
 256     if (msg->file_str_len > 0 &&
 257         OPAL_SUCCESS != (ret = opal_fd_write(fd, msg->file_str_len, file))) {
 258         goto out;
 259     }
 260     if (msg->topic_str_len > 0 &&
 261         OPAL_SUCCESS != (ret = opal_fd_write(fd, msg->topic_str_len, topic))) {
 262         goto out;
 263     }
 264     if (msg->msg_str_len > 0 &&
 265         OPAL_SUCCESS != (ret = opal_fd_write(fd, msg->msg_str_len, str))) {
 266         goto out;
 267     }
 268 
 269  out:
 270     free(str);
 271     return ret;
 272 }
 273 
 274 
 275 /* Called from the child to send an error message up the pipe to the
 276    waiting parent. */
 277 static void send_error_show_help(int fd, int exit_status,
 278                                  const char *file, const char *topic, ...)
 279 {
 280     va_list ap;
 281     orte_odls_pipe_err_msg_t msg;
 282 
 283     msg.fatal = true;
 284     msg.exit_status = exit_status;
 285 
 286     /* Send it */
 287     va_start(ap, topic);
 288     write_help_msg(fd, &msg, file, topic, ap);
 289     va_end(ap);
 290 
 291     exit(exit_status);
 292 }
 293 
 294 static int close_open_file_descriptors(int write_fd,
 295                                       orte_iof_base_io_conf_t opts) {
 296     DIR *dir = opendir("/proc/self/fd");
 297     if (NULL == dir) {
 298         return ORTE_ERR_FILE_OPEN_FAILURE;
 299     }
 300     struct dirent *files;
 301 
 302     /* grab the fd of the opendir above so we don't close in the 
 303      * middle of the scan. */
 304     int dir_scan_fd = dirfd(dir);
 305     if(dir_scan_fd < 0 ) {
 306         return ORTE_ERR_FILE_OPEN_FAILURE;
 307     }
 308 
 309 
 310     while (NULL != (files = readdir(dir))) {
 311         if (!isdigit(files->d_name[0])) {
 312             continue;
 313         }
 314         int fd = strtol(files->d_name, NULL, 10);
 315         if (errno == EINVAL || errno == ERANGE) {
 316             closedir(dir);
 317             return ORTE_ERR_TYPE_MISMATCH;
 318         }
 319         if (fd >=3 &&
 320 #if OPAL_PMIX_V1
 321             fd != opts.p_internal[1] &&
 322 #endif
 323             fd != write_fd && 
 324             fd != dir_scan_fd) {
 325             close(fd);
 326         }
 327     }
 328     closedir(dir);
 329     return ORTE_SUCCESS;
 330 }
 331 
 332 static int do_child(orte_odls_spawn_caddy_t *cd, int write_fd)
 333 {
 334     int i;
 335     sigset_t sigs;
 336 
 337     /* Setup the pipe to be close-on-exec */
 338     opal_fd_set_cloexec(write_fd);
 339 
 340     if (NULL != cd->child) {
 341         /* setup stdout/stderr so that any error messages that we
 342            may print out will get displayed back at orterun.
 343 
 344            NOTE: Definitely do this AFTER we check contexts so
 345            that any error message from those two functions doesn't
 346            come out to the user. IF we didn't do it in this order,
 347            THEN a user who gives us a bad executable name or
 348            working directory would get N error messages, where
 349            N=num_procs. This would be very annoying for large
 350            jobs, so instead we set things up so that orterun
 351            always outputs a nice, single message indicating what
 352            happened
 353         */
 354 
 355         if (ORTE_FLAG_TEST(cd->jdata, ORTE_JOB_FLAG_FORWARD_OUTPUT)) {
 356             if (ORTE_SUCCESS != (i = orte_iof_base_setup_child(&cd->opts, &cd->env))) {
 357                 ORTE_ERROR_LOG(i);
 358                 send_error_show_help(write_fd, 1,
 359                                      "help-orte-odls-alps.txt",
 360                                      "iof setup failed",
 361                                      orte_process_info.nodename, cd->app->app);
 362                 /* Does not return */
 363             }
 364         }
 365 
 366 
 367         /* now set any child-level controls such as binding */
 368         orte_rtc.set(cd->jdata, cd->child, &cd->env, write_fd);
 369 
 370     } else if (!ORTE_FLAG_TEST(cd->jdata, ORTE_JOB_FLAG_FORWARD_OUTPUT)) {
 371         /* tie stdin/out/err/internal to /dev/null */
 372         int fdnull;
 373         for (i=0; i < 3; i++) {
 374             fdnull = open("/dev/null", O_RDONLY, 0);
 375             if (fdnull > i && i != write_fd) {
 376                 dup2(fdnull, i);
 377             }
 378             close(fdnull);
 379         }
 380 #if OPAL_PMIX_V1
 381         fdnull = open("/dev/null", O_RDONLY, 0);
 382         if (fdnull > cd->opts.p_internal[1]) {
 383             dup2(fdnull, cd->opts.p_internal[1]);
 384         }
 385         close(fdnull);
 386 #endif
 387     }
 388 
 389     if (ORTE_SUCCESS != close_open_file_descriptors(write_fd, cd->opts)) {
 390         send_error_show_help(write_fd, 1, "help-orte-odls-alps.txt",
 391                              "close fds",
 392                              orte_process_info.nodename, cd->app->app,
 393                              __FILE__, __LINE__);
 394     }
 395 
 396 
 397     if (cd->argv == NULL) {
 398         cd->argv = malloc(sizeof(char*)*2);
 399         cd->argv[0] = strdup(cd->app->app);
 400         cd->argv[1] = NULL;
 401     }
 402 
 403     /* Set signal handlers back to the default.  Do this close to
 404        the exev() because the event library may (and likely will)
 405        reset them.  If we don't do this, the event library may
 406        have left some set that, at least on some OS's, don't get
 407        reset via fork() or exec().  Hence, the launched process
 408        could be unkillable (for example). */
 409 
 410     set_handler_alps(SIGTERM);
 411     set_handler_alps(SIGINT);
 412     set_handler_alps(SIGHUP);
 413     set_handler_alps(SIGPIPE);
 414     set_handler_alps(SIGCHLD);
 415 
 416     /* Unblock all signals, for many of the same reasons that we
 417        set the default handlers, above.  This is noticable on
 418        Linux where the event library blocks SIGTERM, but we don't
 419        want that blocked by the launched process. */
 420     sigprocmask(0, 0, &sigs);
 421     sigprocmask(SIG_UNBLOCK, &sigs, 0);
 422 
 423     /* take us to the correct wdir */
 424     if (NULL != cd->wdir) {
 425         if (0 != chdir(cd->wdir)) {
 426             send_error_show_help(write_fd, 1,
 427                                  "help-orterun.txt",
 428                                  "orterun:wdir-not-found",
 429                                  "orted",
 430                                  cd->wdir,
 431                                  orte_process_info.nodename,
 432                                  (NULL == cd->child) ? 0 : cd->child->app_rank);
 433             /* Does not return */
 434         }
 435     }
 436 
 437     /* Exec the new executable */
 438 
 439     if (10 < opal_output_get_verbosity(orte_odls_base_framework.framework_output)) {
 440         int jout;
 441         opal_output(0, "%s STARTING %s", ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), cd->app->app);
 442         for (jout=0; NULL != cd->argv[jout]; jout++) {
 443             opal_output(0, "%s\tARGV[%d]: %s", ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), jout, cd->argv[jout]);
 444         }
 445         for (jout=0; NULL != cd->env[jout]; jout++) {
 446             opal_output(0, "%s\tENVIRON[%d]: %s", ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), jout, cd->env[jout]);
 447         }
 448     }
 449 
 450     execve(cd->cmd, cd->argv, cd->env);
 451     send_error_show_help(write_fd, 1,
 452                          "help-orte-odls-alps.txt", "execve error",
 453                          orte_process_info.nodename, cd->app->app, strerror(errno));
 454     /* Does not return */
 455 }
 456 
 457 
 458 static int do_parent(orte_odls_spawn_caddy_t *cd, int read_fd)
 459 {
 460     int rc;
 461     orte_odls_pipe_err_msg_t msg;
 462     char file[ORTE_ODLS_MAX_FILE_LEN + 1], topic[ORTE_ODLS_MAX_TOPIC_LEN + 1], *str = NULL;
 463 
 464     if (cd->opts.connect_stdin) {
 465         close(cd->opts.p_stdin[0]);
 466     }
 467     close(cd->opts.p_stdout[1]);
 468     if( !orte_iof_base.redirect_app_stderr_to_stdout ) {
 469         close(cd->opts.p_stderr[1]);
 470     }
 471 #if OPAL_PMIX_V1
 472     close(cd->opts.p_internal[1]);
 473 #endif
 474 
 475     /* Block reading a message from the pipe */
 476     while (1) {
 477         rc = opal_fd_read(read_fd, sizeof(msg), &msg);
 478 
 479         /* If the pipe closed, then the child successfully launched */
 480         if (OPAL_ERR_TIMEOUT == rc) {
 481             break;
 482         }
 483 
 484         /* If Something Bad happened in the read, error out */
 485         if (OPAL_SUCCESS != rc) {
 486             ORTE_ERROR_LOG(rc);
 487             close(read_fd);
 488 
 489             if (NULL != cd->child) {
 490                 cd->child->state = ORTE_PROC_STATE_UNDEF;
 491             }
 492             return rc;
 493         }
 494 
 495         /* Otherwise, we got a warning or error message from the child */
 496         if (NULL != cd->child) {
 497             if (msg.fatal) {
 498                 ORTE_FLAG_UNSET(cd->child, ORTE_PROC_FLAG_ALIVE);
 499             } else {
 500                 ORTE_FLAG_SET(cd->child, ORTE_PROC_FLAG_ALIVE);
 501             }
 502         }
 503 
 504         /* Read in the strings; ensure to terminate them with \0 */
 505         if (msg.file_str_len > 0) {
 506             rc = opal_fd_read(read_fd, msg.file_str_len, file);
 507             if (OPAL_SUCCESS != rc) {
 508                 orte_show_help("help-orte-odls-alps.txt", "syscall fail",
 509                                true,
 510                                orte_process_info.nodename, cd->app,
 511                                "opal_fd_read", __FILE__, __LINE__);
 512                 if (NULL != cd->child) {
 513                     cd->child->state = ORTE_PROC_STATE_UNDEF;
 514                 }
 515                 return rc;
 516             }
 517             file[msg.file_str_len] = '\0';
 518         }
 519         if (msg.topic_str_len > 0) {
 520             rc = opal_fd_read(read_fd, msg.topic_str_len, topic);
 521             if (OPAL_SUCCESS != rc) {
 522                 orte_show_help("help-orte-odls-alps.txt", "syscall fail",
 523                                true,
 524                                orte_process_info.nodename, cd->app,
 525                                "opal_fd_read", __FILE__, __LINE__);
 526                 if (NULL != cd->child) {
 527                     cd->child->state = ORTE_PROC_STATE_UNDEF;
 528                 }
 529                 return rc;
 530             }
 531             topic[msg.topic_str_len] = '\0';
 532         }
 533         if (msg.msg_str_len > 0) {
 534             str = calloc(1, msg.msg_str_len + 1);
 535             if (NULL == str) {
 536                 orte_show_help("help-orte-odls-alps.txt", "syscall fail",
 537                                true,
 538                                orte_process_info.nodename, cd->app,
 539                                "opal_fd_read", __FILE__, __LINE__);
 540                 if (NULL != cd->child) {
 541                     cd->child->state = ORTE_PROC_STATE_UNDEF;
 542                 }
 543                 return rc;
 544             }
 545             rc = opal_fd_read(read_fd, msg.msg_str_len, str);
 546         }
 547 
 548         /* Print out what we got.  We already have a rendered string,
 549            so use orte_show_help_norender(). */
 550         if (msg.msg_str_len > 0) {
 551             orte_show_help_norender(file, topic, false, str);
 552             free(str);
 553             str = NULL;
 554         }
 555 
 556         /* If msg.fatal is true, then the child exited with an error.
 557            Otherwise, whatever we just printed was a warning, so loop
 558            around and see what else is on the pipe (or if the pipe
 559            closed, indicating that the child launched
 560            successfully). */
 561         if (msg.fatal) {
 562             if (NULL != cd->child) {
 563                 cd->child->state = ORTE_PROC_STATE_FAILED_TO_START;
 564                 ORTE_FLAG_UNSET(cd->child, ORTE_PROC_FLAG_ALIVE);
 565             }
 566             close(read_fd);
 567             return ORTE_ERR_FAILED_TO_START;
 568         }
 569     }
 570 
 571     /* If we got here, it means that the pipe closed without
 572        indication of a fatal error, meaning that the child process
 573        launched successfully. */
 574     if (NULL != cd->child) {
 575         cd->child->state = ORTE_PROC_STATE_RUNNING;
 576         ORTE_FLAG_SET(cd->child, ORTE_PROC_FLAG_ALIVE);
 577     }
 578     close(read_fd);
 579 
 580     return ORTE_SUCCESS;
 581 }
 582 
 583 
 584 /**
 585  *  Fork/exec the specified processes
 586  */
 587 static int odls_alps_fork_local_proc(void *cdptr)
 588 {
 589     orte_odls_spawn_caddy_t *cd = (orte_odls_spawn_caddy_t*)cdptr;
 590     int p[2];
 591     pid_t pid;
 592 
 593     /* A pipe is used to communicate between the parent and child to
 594        indicate whether the exec ultimately succeeded or failed.  The
 595        child sets the pipe to be close-on-exec; the child only ever
 596        writes anything to the pipe if there is an error (e.g.,
 597        executable not found, exec() fails, etc.).  The parent does a
 598        blocking read on the pipe; if the pipe closed with no data,
 599        then the exec() succeeded.  If the parent reads something from
 600        the pipe, then the child was letting us know why it failed. */
 601     if (pipe(p) < 0) {
 602         ORTE_ERROR_LOG(ORTE_ERR_SYS_LIMITS_PIPES);
 603         if (NULL != cd->child) {
 604             cd->child->state = ORTE_PROC_STATE_FAILED_TO_START;
 605             cd->child->exit_code = ORTE_ERR_SYS_LIMITS_PIPES;
 606         }
 607         return ORTE_ERR_SYS_LIMITS_PIPES;
 608     }
 609 
 610     /* Fork off the child */
 611     pid = fork();
 612     if (NULL != cd->child) {
 613         cd->child->pid = pid;
 614     }
 615 
 616     if (pid < 0) {
 617         ORTE_ERROR_LOG(ORTE_ERR_SYS_LIMITS_CHILDREN);
 618         if (NULL != cd->child) {
 619             cd->child->state = ORTE_PROC_STATE_FAILED_TO_START;
 620             cd->child->exit_code = ORTE_ERR_SYS_LIMITS_CHILDREN;
 621         }
 622         return ORTE_ERR_SYS_LIMITS_CHILDREN;
 623     }
 624 
 625     if (pid == 0) {
 626         close(p[0]);
 627 #if HAVE_SETPGID
 628         setpgid(0, 0);
 629 #endif
 630         do_child(cd, p[1]);
 631         /* Does not return */
 632     }
 633 
 634     close(p[1]);
 635     return do_parent(cd, p[0]);
 636 }
 637 
 638 
 639 /**
 640  * Launch all processes allocated to the current node.
 641  */
 642 
 643 int orte_odls_alps_launch_local_procs(opal_buffer_t *data)
 644 {
 645     orte_jobid_t job;
 646     int rc;
 647 
 648     /* construct the list of children we are to launch */
 649     if (ORTE_SUCCESS != (rc = orte_odls_base_default_construct_child_list(data, &job))) {
 650         OPAL_OUTPUT_VERBOSE((2, orte_odls_base_framework.framework_output,
 651                              "%s odls:alps:launch:local failed to construct child list on error %s",
 652                              ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), ORTE_ERROR_NAME(rc)));
 653         return rc;
 654     }
 655 
 656     /* get the RDMA credentials and push them into the launch environment */
 657 
 658     if (ORTE_SUCCESS != (rc = orte_odls_alps_get_rdma_creds())) {;
 659         OPAL_OUTPUT_VERBOSE((2, orte_odls_base_framework.framework_output,
 660                              "%s odls:alps:launch:failed to get GNI rdma credentials %s",
 661                              ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), ORTE_ERROR_NAME(rc)));
 662         return rc;
 663     }
 664 
 665     /* launch the local procs */
 666     ORTE_ACTIVATE_LOCAL_LAUNCH(job, odls_alps_fork_local_proc);
 667 
 668     return ORTE_SUCCESS;
 669 }
 670 
 671 
 672 /**
 673  * Send a signal to a pid.  Note that if we get an error, we set the
 674  * return value and let the upper layer print out the message.
 675  */
 676 static int send_signal(pid_t pid, int signal)
 677 {
 678     int rc = ORTE_SUCCESS;
 679 
 680     OPAL_OUTPUT_VERBOSE((1, orte_odls_base_framework.framework_output,
 681                          "%s sending signal %d to pid %ld",
 682                          ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
 683                          signal, (long)pid));
 684 
 685     if (kill(pid, signal) != 0) {
 686         switch(errno) {
 687             case EINVAL:
 688                 rc = ORTE_ERR_BAD_PARAM;
 689                 break;
 690             case ESRCH:
 691                 /* This case can occur when we deliver a signal to a
 692                    process that is no longer there.  This can happen if
 693                    we deliver a signal while the job is shutting down.
 694                    This does not indicate a real problem, so just
 695                    ignore the error.  */
 696                 break;
 697             case EPERM:
 698                 rc = ORTE_ERR_PERM;
 699                 break;
 700             default:
 701                 rc = ORTE_ERROR;
 702         }
 703     }
 704 
 705     return rc;
 706 }
 707 
 708 static int orte_odls_alps_signal_local_procs(const orte_process_name_t *proc, int32_t signal)
 709 {
 710     int rc;
 711 
 712     if (ORTE_SUCCESS != (rc = orte_odls_base_default_signal_local_procs(proc, signal, send_signal))) {
 713         ORTE_ERROR_LOG(rc);
 714         return rc;
 715     }
 716     return ORTE_SUCCESS;
 717 }
 718 
 719 static int orte_odls_alps_restart_proc(orte_proc_t *child)
 720 {
 721     int rc;
 722 
 723     /* restart the local proc */
 724     if (ORTE_SUCCESS != (rc = orte_odls_base_default_restart_proc(child, odls_alps_fork_local_proc))) {
 725         OPAL_OUTPUT_VERBOSE((2, orte_odls_base_framework.framework_output,
 726                              "%s odls:alps:restart_proc failed to launch on error %s",
 727                              ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), ORTE_ERROR_NAME(rc)));
 728     }
 729     return rc;
 730 }

/* [<][>][^][v][top][bottom][index][help] */