diff --git a/orte/mca/odls/alps/odls_alps_module.c b/orte/mca/odls/alps/odls_alps_module.c index f1eaa29ff25..7d0e15d6f69 100644 --- a/orte/mca/odls/alps/odls_alps_module.c +++ b/orte/mca/odls/alps/odls_alps_module.c @@ -144,11 +144,7 @@ static int orte_odls_alps_restart_proc(orte_proc_t *child); static void send_error_show_help(int fd, int exit_status, const char *file, const char *topic, ...) __opal_attribute_noreturn__; -static int do_child(orte_proc_t *child, - char *app, char **argv, - char **environ_copy, - orte_job_t *jobdat, int write_fd, - orte_iof_base_io_conf_t opts) +static int do_child(orte_odls_spawn_caddy_t *cd, int write_fd) __opal_attribute_noreturn__; @@ -342,20 +338,15 @@ static int close_open_file_descriptors(int write_fd, orte_iof_base_io_conf_t opt return ORTE_SUCCESS; } -static int do_child( orte_proc_t *child, - char *app, char **argv, - char **environ_copy, - orte_job_t *jobdat, int write_fd, - orte_iof_base_io_conf_t opts) +static int do_child(orte_odls_spawn_caddy_t *cd, int write_fd) { - int i, rc; + int i; sigset_t sigs; - char *param, *msg; /* Setup the pipe to be close-on-exec */ opal_fd_set_cloexec(write_fd); - if (NULL != child) { + if (NULL != cd->child) { /* setup stdout/stderr so that any error messages that we may print out will get displayed back at orterun. @@ -369,20 +360,19 @@ static int do_child( orte_proc_t *child, always outputs a nice, single message indicating what happened */ - if (ORTE_SUCCESS != (i = orte_iof_base_setup_child(&opts, - &environ_copy))) { + if (ORTE_SUCCESS != (i = orte_iof_base_setup_child(&cd->opts, &cd->env))) { ORTE_ERROR_LOG(i); send_error_show_help(write_fd, 1, "help-orte-odls-alps.txt", "iof setup failed", - orte_process_info.nodename, app); + orte_process_info.nodename, cd->app->app); /* Does not return */ } /* now set any child-level controls such as binding */ - orte_rtc.set(jobdat, child, &environ_copy, write_fd); + orte_rtc.set(cd->jdata, cd->child, &cd->env, write_fd); - } else if (!ORTE_FLAG_TEST(jobdat, ORTE_JOB_FLAG_FORWARD_OUTPUT)) { + } else if (!ORTE_FLAG_TEST(cd->jdata, ORTE_JOB_FLAG_FORWARD_OUTPUT)) { /* tie stdin/out/err/internal to /dev/null */ int fdnull; for (i=0; i < 3; i++) { @@ -393,24 +383,24 @@ static int do_child( orte_proc_t *child, close(fdnull); } fdnull = open("/dev/null", O_RDONLY, 0); - if (fdnull > opts.p_internal[1]) { - dup2(fdnull, opts.p_internal[1]); + if (fdnull > cd->opts.p_internal[1]) { + dup2(fdnull, cd->opts.p_internal[1]); } close(fdnull); } - if (ORTE_SUCCESS != close_open_file_descriptors(write_fd, opts)) { + if (ORTE_SUCCESS != close_open_file_descriptors(write_fd, cd->opts)) { send_error_show_help(write_fd, 1, "help-orte-odls-alps.txt", "close fds", - orte_process_info.nodename, app, + orte_process_info.nodename, cd->app->app, __FILE__, __LINE__); } - if (argv == NULL) { - argv = malloc(sizeof(char*)*2); - argv[0] = strdup(app); - argv[1] = NULL; + if (cd->argv == NULL) { + cd->argv = malloc(sizeof(char*)*2); + cd->argv[0] = strdup(cd->app->app); + cd->argv[1] = NULL; } /* Set signal handlers back to the default. Do this close to @@ -437,37 +427,33 @@ static int do_child( orte_proc_t *child, if (10 < opal_output_get_verbosity(orte_odls_base_framework.framework_output)) { int jout; - opal_output(0, "%s STARTING %s", ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), app); - for (jout=0; NULL != argv[jout]; jout++) { - opal_output(0, "%s\tARGV[%d]: %s", ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), jout, argv[jout]); + opal_output(0, "%s STARTING %s", ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), cd->app->app); + for (jout=0; NULL != cd->argv[jout]; jout++) { + opal_output(0, "%s\tARGV[%d]: %s", ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), jout, cd->argv[jout]); } - for (jout=0; NULL != environ_copy[jout]; jout++) { - opal_output(0, "%s\tENVIRON[%d]: %s", ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), jout, environ_copy[jout]); + for (jout=0; NULL != cd->env[jout]; jout++) { + opal_output(0, "%s\tENVIRON[%d]: %s", ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), jout, cd->env[jout]); } } - execve(app, argv, environ_copy); + execve(cd->app->app, cd->argv, cd->env); send_error_show_help(write_fd, 1, "help-orte-odls-alps.txt", "execve error", - orte_process_info.nodename, app, strerror(errno)); + orte_process_info.nodename, cd->app->app, strerror(errno)); /* Does not return */ } -static int do_parent(orte_proc_t *child, - char *app, char **argv, - char **environ_copy, - orte_job_t *jobdat, int read_fd, - orte_iof_base_io_conf_t opts) +static int do_parent(orte_odls_spawn_caddy_t *cd, int read_fd) { int rc; orte_odls_pipe_err_msg_t msg; char file[ORTE_ODLS_MAX_FILE_LEN + 1], topic[ORTE_ODLS_MAX_TOPIC_LEN + 1], *str = NULL; - close(opts.p_stdin[0]); - close(opts.p_stdout[1]); - close(opts.p_stderr[1]); - close(opts.p_internal[1]); + close(cd->opts.p_stdin[0]); + close(cd->opts.p_stdout[1]); + close(cd->opts.p_stderr[1]); + close(cd->opts.p_internal[1]); /* Block reading a message from the pipe */ while (1) { @@ -483,18 +469,18 @@ static int do_parent(orte_proc_t *child, ORTE_ERROR_LOG(rc); close(read_fd); - if (NULL != child) { - child->state = ORTE_PROC_STATE_UNDEF; + if (NULL != cd->child) { + cd->child->state = ORTE_PROC_STATE_UNDEF; } return rc; } /* Otherwise, we got a warning or error message from the child */ - if (NULL != child) { + if (NULL != cd->child) { if (msg.fatal) { - ORTE_FLAG_UNSET(child, ORTE_PROC_FLAG_ALIVE); + ORTE_FLAG_UNSET(cd->child, ORTE_PROC_FLAG_ALIVE); } else { - ORTE_FLAG_SET(child, ORTE_PROC_FLAG_ALIVE); + ORTE_FLAG_SET(cd->child, ORTE_PROC_FLAG_ALIVE); } } @@ -504,10 +490,10 @@ static int do_parent(orte_proc_t *child, if (OPAL_SUCCESS != rc) { orte_show_help("help-orte-odls-alps.txt", "syscall fail", true, - orte_process_info.nodename, app, + orte_process_info.nodename, cd->app, "opal_fd_read", __FILE__, __LINE__); - if (NULL != child) { - child->state = ORTE_PROC_STATE_UNDEF; + if (NULL != cd->child) { + cd->child->state = ORTE_PROC_STATE_UNDEF; } return rc; } @@ -518,10 +504,10 @@ static int do_parent(orte_proc_t *child, if (OPAL_SUCCESS != rc) { orte_show_help("help-orte-odls-alps.txt", "syscall fail", true, - orte_process_info.nodename, app, + orte_process_info.nodename, cd->app, "opal_fd_read", __FILE__, __LINE__); - if (NULL != child) { - child->state = ORTE_PROC_STATE_UNDEF; + if (NULL != cd->child) { + cd->child->state = ORTE_PROC_STATE_UNDEF; } return rc; } @@ -532,10 +518,10 @@ static int do_parent(orte_proc_t *child, if (NULL == str) { orte_show_help("help-orte-odls-alps.txt", "syscall fail", true, - orte_process_info.nodename, app, + orte_process_info.nodename, cd->app, "opal_fd_read", __FILE__, __LINE__); - if (NULL != child) { - child->state = ORTE_PROC_STATE_UNDEF; + if (NULL != cd->child) { + cd->child->state = ORTE_PROC_STATE_UNDEF; } return rc; } @@ -556,9 +542,9 @@ static int do_parent(orte_proc_t *child, closed, indicating that the child launched successfully). */ if (msg.fatal) { - if (NULL != child) { - child->state = ORTE_PROC_STATE_FAILED_TO_START; - ORTE_FLAG_UNSET(child, ORTE_PROC_FLAG_ALIVE); + if (NULL != cd->child) { + cd->child->state = ORTE_PROC_STATE_FAILED_TO_START; + ORTE_FLAG_UNSET(cd->child, ORTE_PROC_FLAG_ALIVE); } close(read_fd); return ORTE_ERR_FAILED_TO_START; @@ -568,9 +554,9 @@ static int do_parent(orte_proc_t *child, /* If we got here, it means that the pipe closed without indication of a fatal error, meaning that the child process launched successfully. */ - if (NULL != child) { - child->state = ORTE_PROC_STATE_RUNNING; - ORTE_FLAG_SET(child, ORTE_PROC_FLAG_ALIVE); + if (NULL != cd->child) { + cd->child->state = ORTE_PROC_STATE_RUNNING; + ORTE_FLAG_SET(cd->child, ORTE_PROC_FLAG_ALIVE); } close(read_fd); @@ -581,14 +567,10 @@ static int do_parent(orte_proc_t *child, /** * Fork/exec the specified processes */ -static int odls_alps_fork_local_proc(orte_proc_t *child, - char *app, - char **argv, - char **environ_copy, - orte_job_t *jobdat, - orte_iof_base_io_conf_t opts) +static int odls_alps_fork_local_proc(void *cdptr) { - int rc, p[2]; + orte_odls_spawn_caddy_t *cd = (orte_odls_spawn_caddy_t*)cdptr; + int p[2]; pid_t pid; /* A pipe is used to communicate between the parent and child to @@ -601,24 +583,24 @@ static int odls_alps_fork_local_proc(orte_proc_t *child, the pipe, then the child was letting us know why it failed. */ if (pipe(p) < 0) { ORTE_ERROR_LOG(ORTE_ERR_SYS_LIMITS_PIPES); - if (NULL != child) { - child->state = ORTE_PROC_STATE_FAILED_TO_START; - child->exit_code = ORTE_ERR_SYS_LIMITS_PIPES; + if (NULL != cd->child) { + cd->child->state = ORTE_PROC_STATE_FAILED_TO_START; + cd->child->exit_code = ORTE_ERR_SYS_LIMITS_PIPES; } return ORTE_ERR_SYS_LIMITS_PIPES; } /* Fork off the child */ pid = fork(); - if (NULL != child) { - child->pid = pid; + if (NULL != cd->child) { + cd->child->pid = pid; } if (pid < 0) { ORTE_ERROR_LOG(ORTE_ERR_SYS_LIMITS_CHILDREN); - if (NULL != child) { - child->state = ORTE_PROC_STATE_FAILED_TO_START; - child->exit_code = ORTE_ERR_SYS_LIMITS_CHILDREN; + if (NULL != cd->child) { + cd->child->state = ORTE_PROC_STATE_FAILED_TO_START; + cd->child->exit_code = ORTE_ERR_SYS_LIMITS_CHILDREN; } return ORTE_ERR_SYS_LIMITS_CHILDREN; } @@ -628,12 +610,12 @@ static int odls_alps_fork_local_proc(orte_proc_t *child, #if HAVE_SETPGID setpgid(0, 0); #endif - do_child(child, app, argv, environ_copy, jobdat, p[1], opts); + do_child(cd, p[1]); /* Does not return */ } close(p[1]); - return do_parent(child, app, argv, environ_copy, jobdat, p[0], opts); + return do_parent(cd, p[0]); } @@ -643,8 +625,8 @@ static int odls_alps_fork_local_proc(orte_proc_t *child, int orte_odls_alps_launch_local_procs(opal_buffer_t *data) { - int rc; orte_jobid_t job; + int rc; /* construct the list of children we are to launch */ if (ORTE_SUCCESS != (rc = orte_odls_base_default_construct_child_list(data, &job))) { @@ -729,4 +711,3 @@ static int orte_odls_alps_restart_proc(orte_proc_t *child) } return rc; } - diff --git a/orte/mca/odls/base/odls_base_default_fns.c b/orte/mca/odls/base/odls_base_default_fns.c index 4f6ad2c95ca..71417064d50 100644 --- a/orte/mca/odls/base/odls_base_default_fns.c +++ b/orte/mca/odls/base/odls_base_default_fns.c @@ -507,7 +507,7 @@ int orte_odls_base_default_construct_child_list(opal_buffer_t *buffer, return rc; } -static int setup_path(orte_app_context_t *app) +static int setup_path(orte_app_context_t *app, char **wdir) { int rc; char dir[MAXPATHLEN]; @@ -539,9 +539,12 @@ static int setup_path(orte_app_context_t *app) * ensuring they start out matching. */ getcwd(dir, sizeof(dir)); + *wdir = strdup(dir); opal_setenv("PWD", dir, true, &app->env); /* update the initial wdir value too */ opal_setenv(OPAL_MCA_PREFIX"initial_wdir", dir, true, &app->env); + } else { + *wdir = NULL; } /* Search for the OMPI_exec_path and PATH settings in the environment. */ @@ -631,24 +634,26 @@ void orte_odls_base_spawn_proc(int fd, short sd, void *cbdata) orte_job_t *jobdat = cd->jdata; orte_app_context_t *app = cd->app; orte_proc_t *child = cd->child; - char **env = NULL, **argv = NULL, *cmd = NULL; int rc, i; bool found; + orte_proc_state_t state; /* thread-protect common values */ - env = opal_argv_copy(app->env); - - /* setup the pmix environment */ - if (OPAL_SUCCESS != (rc = opal_pmix.server_setup_fork(&child->name, &env))) { - ORTE_ERROR_LOG(rc); - goto errorout; - } + cd->env = opal_argv_copy(app->env); /* ensure we clear any prior info regarding state or exit status in * case this is a restart */ child->exit_code = 0; ORTE_FLAG_UNSET(child, ORTE_PROC_FLAG_WAITPID); + + /* setup the pmix environment */ + if (OPAL_SUCCESS != (rc = opal_pmix.server_setup_fork(&child->name, &cd->env))) { + ORTE_ERROR_LOG(rc); + state = ORTE_PROC_STATE_FAILED_TO_LAUNCH; + goto errorout; + } + /* if we are not forwarding output for this job, then * flag iof as complete */ @@ -677,69 +682,70 @@ void orte_odls_base_spawn_proc(int fd, short sd, void *cbdata) child->name.vpid == nm->name.vpid) { /* we want this one - modify the app's command to include * the orte xterm cmd that starts with the xtermcmd */ - argv = opal_argv_copy(orte_odls_globals.xtermcmd); + cd->argv = opal_argv_copy(orte_odls_globals.xtermcmd); /* insert the rank into the correct place as a window title */ - free(argv[2]); - asprintf(&argv[2], "Rank %s", ORTE_VPID_PRINT(child->name.vpid)); + free(cd->argv[2]); + asprintf(&cd->argv[2], "Rank %s", ORTE_VPID_PRINT(child->name.vpid)); /* add in the argv from the app */ for (i=0; NULL != app->argv[i]; i++) { - opal_argv_append_nosize(&argv, app->argv[i]); + opal_argv_append_nosize(&cd->argv, app->argv[i]); } /* use the xterm cmd as the app string */ - cmd = strdup(orte_odls_globals.xtermcmd[0]); + cd->cmd = strdup(orte_odls_globals.xtermcmd[0]); found = true; break; } else if (jobdat->num_procs <= nm->name.vpid) { /* check for bozo case */ /* can't be done! */ orte_show_help("help-orte-odls-base.txt", "orte-odls-base:xterm-rank-out-of-bounds", - true, nm->name.vpid, jobdat->num_procs); - child->exit_code = ORTE_PROC_STATE_FAILED_TO_LAUNCH; + true, orte_process_info.nodename, + nm->name.vpid, jobdat->num_procs); + state = ORTE_PROC_STATE_FAILED_TO_LAUNCH; goto errorout; } } if (!found) { - cmd = strdup(app->app); - argv = opal_argv_copy(app->argv); + cd->cmd = strdup(app->app); + cd->argv = opal_argv_copy(app->argv); } } else if (NULL != orte_fork_agent) { /* we were given a fork agent - use it */ - argv = opal_argv_copy(orte_fork_agent); + cd->argv = opal_argv_copy(orte_fork_agent); /* add in the argv from the app */ for (i=0; NULL != app->argv[i]; i++) { - opal_argv_append_nosize(&argv, app->argv[i]); + opal_argv_append_nosize(&cd->argv, app->argv[i]); } /* the app exe name itself is in the argvsav array, so * we can recover it from there later */ - cmd = opal_path_findv(orte_fork_agent[0], X_OK, orte_launch_environ, NULL); - if (NULL == cmd) { + cd->cmd = opal_path_findv(orte_fork_agent[0], X_OK, orte_launch_environ, NULL); + if (NULL == cd->cmd) { orte_show_help("help-orte-odls-base.txt", "orte-odls-base:fork-agent-not-found", true, orte_process_info.nodename, orte_fork_agent[0]); - child->exit_code = ORTE_PROC_STATE_FAILED_TO_LAUNCH; + state = ORTE_PROC_STATE_FAILED_TO_LAUNCH; goto errorout; } } else { - cmd = strdup(app->app); - argv = opal_argv_copy(app->argv); + cd->cmd = strdup(app->app); + cd->argv = opal_argv_copy(app->argv); } /* setup the rest of the environment with the proc-specific items - these * will be overwritten for each child */ - if (ORTE_SUCCESS != (rc = orte_schizo.setup_child(jobdat, child, app, &env))) { + if (ORTE_SUCCESS != (rc = orte_schizo.setup_child(jobdat, child, app, &cd->env))) { ORTE_ERROR_LOG(rc); - child->exit_code = rc; + state = ORTE_PROC_STATE_FAILED_TO_LAUNCH; goto errorout; } /* if we are indexing the argv by rank, do so now */ if (cd->index_argv) { char *param; - asprintf(¶m, "%s-%d", argv[0], (int)child->name.vpid); - free(argv[0]); - argv[0] = param; + asprintf(¶m, "%s-%d", cd->argv[0], (int)child->name.vpid); + free(cd->argv[0]); + cd->argv[0] = param; } if (5 < opal_output_get_verbosity(orte_odls_base_framework.framework_output)) { @@ -753,45 +759,19 @@ void orte_odls_base_spawn_proc(int fd, short sd, void *cbdata) } } - if (ORTE_SUCCESS != (rc = cd->fork_local(child, cmd, argv, env, jobdat, cd->opts))) { - child->exit_code = rc; /* error message already output */ - goto errorout; - } - if (ORTE_SUCCESS != rc) { - /* do NOT ERROR_LOG this error - it generates - * a message/node as most errors will be common - * across the entire cluster. Instead, we let orterun - * output a consolidated error message for us - */ - ORTE_FLAG_UNSET(child, ORTE_PROC_FLAG_ALIVE); - child->exit_code = rc; /* error message already output */ + if (ORTE_SUCCESS != (rc = cd->fork_local(cd))) { + /* error message already output */ + state = ORTE_PROC_STATE_FAILED_TO_START; goto errorout; } ORTE_ACTIVATE_PROC_STATE(&child->name, ORTE_PROC_STATE_RUNNING); - if (NULL != env) { - opal_argv_free(env); - } - if (NULL != argv) { - opal_argv_free(argv); - } - if (NULL != cmd) { - free(cmd); - } OBJ_RELEASE(cd); return; errorout: - ORTE_ACTIVATE_PROC_STATE(&child->name, ORTE_PROC_STATE_FAILED_TO_START); - if (NULL != env) { - opal_argv_free(env); - } - if (NULL != argv) { - opal_argv_free(argv); - } - if (NULL != cmd) { - free(cmd); - } + ORTE_FLAG_UNSET(child, ORTE_PROC_FLAG_ALIVE); + ORTE_ACTIVATE_PROC_STATE(&child->name, state); OBJ_RELEASE(cd); } @@ -811,6 +791,7 @@ void orte_odls_base_default_launch_local(int fd, short sd, void *cbdata) char *msg; orte_odls_spawn_caddy_t *cd; opal_event_base_t *evb; + char *effective_dir = NULL; opal_output_verbose(5, orte_odls_base_framework.framework_output, "%s local:launch", @@ -949,7 +930,7 @@ void orte_odls_base_default_launch_local(int fd, short sd, void *cbdata) /* setup the working directory for this app - will jump us * to that directory */ - if (ORTE_SUCCESS != (rc = setup_path(app))) { + if (ORTE_SUCCESS != (rc = setup_path(app, &effective_dir))) { OPAL_OUTPUT_VERBOSE((5, orte_odls_base_framework.framework_output, "%s odls:launch:setup_path failed with error %s(%d)", ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), @@ -1013,6 +994,15 @@ void orte_odls_base_default_launch_local(int fd, short sd, void *cbdata) goto GETOUT; } + /* reset our working directory back to our default location - if we + * don't do this, then we will be looking for relative paths starting + * from the last wdir option specified by the user. Thus, we would + * be requiring that the user keep track on the cmd line of where + * each app was located relative to the prior app, instead of relative + * to their current location + */ + chdir(basedir); + /* okay, now let's launch all the local procs for this app using the provided fork_local fn */ for (idx=0; idx < orte_local_children->size; idx++) { if (NULL == (child = (orte_proc_t*)opal_pointer_array_get_item(orte_local_children, idx))) { @@ -1070,6 +1060,9 @@ void orte_odls_base_default_launch_local(int fd, short sd, void *cbdata) /* dispatch this child to the next available launch thread */ cd = OBJ_NEW(orte_odls_spawn_caddy_t); + if (NULL != effective_dir) { + cd->wdir = strdup(effective_dir); + } cd->jdata = jobdat; cd->app = app; cd->child = child; @@ -1118,14 +1111,9 @@ void orte_odls_base_default_launch_local(int fd, short sd, void *cbdata) opal_event_active(&cd->ev, OPAL_EV_WRITE, 1); } - /* reset our working directory back to our default location - if we - * don't do this, then we will be looking for relative paths starting - * from the last wdir option specified by the user. Thus, we would - * be requiring that the user keep track on the cmd line of where - * each app was located relative to the prior app, instead of relative - * to their current location - */ - chdir(basedir); + if (NULL != effective_dir) { + free(effective_dir); + } } GETOUT: @@ -1686,7 +1674,9 @@ int orte_odls_base_default_restart_proc(orte_proc_t *child, orte_app_context_t *app; orte_job_t *jobdat; char basedir[MAXPATHLEN]; - orte_iof_base_io_conf_t opts; + char *wdir = NULL; + orte_odls_spawn_caddy_t *cd; + opal_event_base_t *evb; OPAL_OUTPUT_VERBOSE((5, orte_odls_base_framework.framework_output, "%s odls:restart_proc for proc %s", @@ -1724,35 +1714,71 @@ int orte_odls_base_default_restart_proc(orte_proc_t *child, } /* setup the path */ - if (ORTE_SUCCESS != (rc = setup_path(app))) { + if (ORTE_SUCCESS != (rc = setup_path(app, &wdir))) { ORTE_ERROR_LOG(rc); goto CLEANUP; } + /* dispatch this child to the next available launch thread */ + cd = OBJ_NEW(orte_odls_spawn_caddy_t); + if (NULL != wdir) { + cd->wdir = strdup(wdir); + free(wdir); + } + cd->jdata = jobdat; + cd->app = app; + cd->child = child; + cd->fork_local = fork_local; /* setup any IOF */ - memset(&opts, 0, sizeof(orte_iof_base_io_conf_t)); + cd->opts.usepty = OPAL_ENABLE_PTY_SUPPORT; + + /* do we want to setup stdin? */ + if (jobdat->stdin_target == ORTE_VPID_WILDCARD || + child->name.vpid == jobdat->stdin_target) { + cd->opts.connect_stdin = true; + } else { + cd->opts.connect_stdin = false; + } + if (ORTE_SUCCESS != (rc = orte_iof_base_setup_prefork(&cd->opts))) { + ORTE_ERROR_LOG(rc); + child->exit_code = rc; + OBJ_RELEASE(cd); + ORTE_ACTIVATE_PROC_STATE(&child->name, ORTE_PROC_STATE_FAILED_TO_LAUNCH); + goto CLEANUP; + } if (ORTE_FLAG_TEST(jobdat, ORTE_JOB_FLAG_FORWARD_OUTPUT)) { /* connect endpoints IOF */ - rc = orte_iof_base_setup_parent(&child->name, &opts); + rc = orte_iof_base_setup_parent(&child->name, &cd->opts); if (ORTE_SUCCESS != rc) { ORTE_ERROR_LOG(rc); - ORTE_ACTIVATE_PROC_STATE(&child->name, ORTE_PROC_STATE_FAILED_TO_START); + OBJ_RELEASE(cd); + ORTE_ACTIVATE_PROC_STATE(&child->name, ORTE_PROC_STATE_FAILED_TO_LAUNCH); goto CLEANUP; } } + orte_wait_cb(child, odls_base_default_wait_local_proc, NULL); + ++orte_odls_globals.next_base; + if (orte_odls_globals.num_threads <= orte_odls_globals.next_base) { + orte_odls_globals.next_base = 0; + } OPAL_OUTPUT_VERBOSE((5, orte_odls_base_framework.framework_output, "%s restarting app %s", ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), app->app)); - orte_wait_cb(child, odls_base_default_wait_local_proc, NULL); - if (ORTE_SUCCESS != (rc = fork_local(child, app->app, app->argv, app->env, jobdat, opts))) { + evb = orte_odls_globals.ev_bases[orte_odls_globals.next_base]; + opal_event_set(evb, &cd->ev, -1, + OPAL_EV_WRITE, orte_odls_base_spawn_proc, cd); + opal_event_set_priority(&cd->ev, ORTE_MSG_PRI); + opal_event_active(&cd->ev, OPAL_EV_WRITE, 1); + + if (ORTE_SUCCESS != (rc = fork_local(cd))) { orte_wait_cb_cancel(child); child->exit_code = ORTE_ERR_SILENT; /* error message already output */ ORTE_ACTIVATE_PROC_STATE(&child->name, ORTE_PROC_STATE_FAILED_TO_START); } - CLEANUP: + CLEANUP: OPAL_OUTPUT_VERBOSE((5, orte_odls_base_framework.framework_output, "%s odls:restart of proc %s %s", ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), diff --git a/orte/mca/odls/base/odls_base_frame.c b/orte/mca/odls/base/odls_base_frame.c index c161ae731ba..919e303c6b5 100644 --- a/orte/mca/odls/base/odls_base_frame.c +++ b/orte/mca/odls/base/odls_base_frame.c @@ -239,7 +239,26 @@ OBJ_CLASS_INSTANCE(orte_odls_launch_local_t, static void sccon(orte_odls_spawn_caddy_t *p) { memset(&p->opts, 0, sizeof(orte_iof_base_io_conf_t)); + p->cmd = NULL; + p->wdir = NULL; + p->argv = NULL; + p->env = NULL; +} +static void scdes(orte_odls_spawn_caddy_t *p) +{ + if (NULL != p->cmd) { + free(p->cmd); + } + if (NULL != p->wdir) { + free(p->wdir); + } + if (NULL != p->argv) { + opal_argv_free(p->argv); + } + if (NULL != p->env) { + opal_argv_free(p->env); + } } OBJ_CLASS_INSTANCE(orte_odls_spawn_caddy_t, opal_object_t, - sccon, NULL); + sccon, scdes); diff --git a/orte/mca/odls/base/odls_private.h b/orte/mca/odls/base/odls_private.h index e5e93a8c64f..4d93c2ceb2c 100644 --- a/orte/mca/odls/base/odls_private.h +++ b/orte/mca/odls/base/odls_private.h @@ -82,16 +82,16 @@ orte_odls_base_default_construct_child_list(opal_buffer_t *data, ORTE_DECLSPEC void orte_odls_base_spawn_proc(int fd, short sd, void *cbdata); /* define a function that will fork a local proc */ -typedef int (*orte_odls_base_fork_local_proc_fn_t)(orte_proc_t *child, - char *app, char **argv, - char **environ_copy, - orte_job_t *jdata, - orte_iof_base_io_conf_t opts); +typedef int (*orte_odls_base_fork_local_proc_fn_t)(void *cd); /* define an object for fork/exec the local proc */ typedef struct { opal_object_t super; opal_event_t ev; + char *cmd; + char *wdir; + char **argv; + char **env; orte_job_t *jdata; orte_app_context_t *app; orte_proc_t *child; diff --git a/orte/mca/odls/default/odls_default_module.c b/orte/mca/odls/default/odls_default_module.c index 0e1683e1c9f..5ad54b93fb3 100644 --- a/orte/mca/odls/default/odls_default_module.c +++ b/orte/mca/odls/default/odls_default_module.c @@ -145,11 +145,7 @@ static void send_error_show_help(int fd, int exit_status, const char *file, const char *topic, ...) __opal_attribute_noreturn__; -static int do_child(orte_proc_t *child, - char *cmd, char **argv, - char **environ_copy, - orte_job_t *jobdat, int write_fd, - orte_iof_base_io_conf_t opts) +static int do_child(orte_odls_spawn_caddy_t *cd, int write_fd) __opal_attribute_noreturn__; @@ -319,15 +315,12 @@ static int close_open_file_descriptors(int write_fd, return ORTE_SUCCESS; } -static int do_child(orte_proc_t *child, - char *app, char **argv, - char **environ_copy, - orte_job_t *jobdat, int write_fd, - orte_iof_base_io_conf_t opts) +static int do_child(orte_odls_spawn_caddy_t *cd, int write_fd) { int i; sigset_t sigs; long fd, fdmax = sysconf(_SC_OPEN_MAX); + char dir[MAXPATHLEN]; #if HAVE_SETPGID /* Set a new process group for this child, so that any @@ -338,7 +331,7 @@ static int do_child(orte_proc_t *child, /* Setup the pipe to be close-on-exec */ opal_fd_set_cloexec(write_fd); - if (NULL != child) { + if (NULL != cd->child) { /* setup stdout/stderr so that any error messages that we may print out will get displayed back at orterun. @@ -352,22 +345,21 @@ static int do_child(orte_proc_t *child, always outputs a nice, single message indicating what happened */ - if (ORTE_FLAG_TEST(jobdat, ORTE_JOB_FLAG_FORWARD_OUTPUT)) { - if (ORTE_SUCCESS != (i = orte_iof_base_setup_child(&opts, - &environ_copy))) { + if (ORTE_FLAG_TEST(cd->jdata, ORTE_JOB_FLAG_FORWARD_OUTPUT)) { + if (ORTE_SUCCESS != (i = orte_iof_base_setup_child(&cd->opts, &cd->env))) { ORTE_ERROR_LOG(i); send_error_show_help(write_fd, 1, "help-orte-odls-default.txt", "iof setup failed", - orte_process_info.nodename, app); + orte_process_info.nodename, cd->app->app); /* Does not return */ } } /* now set any child-level controls such as binding */ - orte_rtc.set(jobdat, child, &environ_copy, write_fd); + orte_rtc.set(cd->jdata, cd->child, &cd->env, write_fd); - } else if (!ORTE_FLAG_TEST(jobdat, ORTE_JOB_FLAG_FORWARD_OUTPUT)) { + } else if (!ORTE_FLAG_TEST(cd->jdata, ORTE_JOB_FLAG_FORWARD_OUTPUT)) { /* tie stdin/out/err/internal to /dev/null */ int fdnull; for (i=0; i < 3; i++) { @@ -378,8 +370,8 @@ static int do_child(orte_proc_t *child, close(fdnull); } fdnull = open("/dev/null", O_RDONLY, 0); - if (fdnull > opts.p_internal[1]) { - dup2(fdnull, opts.p_internal[1]); + if (fdnull > cd->opts.p_internal[1]) { + dup2(fdnull, cd->opts.p_internal[1]); } close(fdnull); } @@ -387,19 +379,19 @@ static int do_child(orte_proc_t *child, /* close all open file descriptors w/ exception of stdin/stdout/stderr, the pipe used for the IOF INTERNAL messages, and the pipe up to the parent. */ - if (ORTE_SUCCESS != close_open_file_descriptors(write_fd, opts)) { + if (ORTE_SUCCESS != close_open_file_descriptors(write_fd, cd->opts)) { // close *all* file descriptors -- slow for(fd=3; fdopts.p_internal[1] && fd != write_fd) { close(fd); } } } - if (argv == NULL) { - argv = malloc(sizeof(char*)*2); - argv[0] = strdup(app); - argv[1] = NULL; + if (cd->argv == NULL) { + cd->argv = malloc(sizeof(char*)*2); + cd->argv[0] = strdup(cd->app->app); + cd->argv[1] = NULL; } /* Set signal handlers back to the default. Do this close to @@ -422,30 +414,31 @@ static int do_child(orte_proc_t *child, sigprocmask(0, 0, &sigs); sigprocmask(SIG_UNBLOCK, &sigs, 0); - /* Exec the new executable */ + /* take us to the correct wdir */ + if (NULL != cd->wdir) { + chdir(cd->wdir); + } - execve(app, argv, environ_copy); + /* Exec the new executable */ + execve(cd->app->app, cd->argv, cd->env); + getcwd(dir, sizeof(dir)); send_error_show_help(write_fd, 1, "help-orte-odls-default.txt", "execve error", - orte_process_info.nodename, app, strerror(errno)); + orte_process_info.nodename, dir, cd->app->app, strerror(errno)); /* Does not return */ } -static int do_parent(orte_proc_t *child, - char *app, char **argv, - char **environ_copy, - orte_job_t *jobdat, int read_fd, - orte_iof_base_io_conf_t opts) +static int do_parent(orte_odls_spawn_caddy_t *cd, int read_fd) { int rc; orte_odls_pipe_err_msg_t msg; char file[ORTE_ODLS_MAX_FILE_LEN + 1], topic[ORTE_ODLS_MAX_TOPIC_LEN + 1], *str = NULL; - close(opts.p_stdin[0]); - close(opts.p_stdout[1]); - close(opts.p_stderr[1]); - close(opts.p_internal[1]); + close(cd->opts.p_stdin[0]); + close(cd->opts.p_stdout[1]); + close(cd->opts.p_stderr[1]); + close(cd->opts.p_internal[1]); /* Block reading a message from the pipe */ while (1) { @@ -461,18 +454,18 @@ static int do_parent(orte_proc_t *child, ORTE_ERROR_LOG(rc); close(read_fd); - if (NULL != child) { - child->state = ORTE_PROC_STATE_UNDEF; + if (NULL != cd->child) { + cd->child->state = ORTE_PROC_STATE_UNDEF; } return rc; } /* Otherwise, we got a warning or error message from the child */ - if (NULL != child) { + if (NULL != cd->child) { if (msg.fatal) { - ORTE_FLAG_UNSET(child, ORTE_PROC_FLAG_ALIVE); + ORTE_FLAG_UNSET(cd->child, ORTE_PROC_FLAG_ALIVE); } else { - ORTE_FLAG_SET(child, ORTE_PROC_FLAG_ALIVE); + ORTE_FLAG_SET(cd->child, ORTE_PROC_FLAG_ALIVE); } } @@ -482,10 +475,10 @@ static int do_parent(orte_proc_t *child, if (OPAL_SUCCESS != rc) { orte_show_help("help-orte-odls-default.txt", "syscall fail", true, - orte_process_info.nodename, app, + orte_process_info.nodename, cd->app->app, "opal_fd_read", __FILE__, __LINE__); - if (NULL != child) { - child->state = ORTE_PROC_STATE_UNDEF; + if (NULL != cd->child) { + cd->child->state = ORTE_PROC_STATE_UNDEF; } return rc; } @@ -496,10 +489,10 @@ static int do_parent(orte_proc_t *child, if (OPAL_SUCCESS != rc) { orte_show_help("help-orte-odls-default.txt", "syscall fail", true, - orte_process_info.nodename, app, + orte_process_info.nodename, cd->app->app, "opal_fd_read", __FILE__, __LINE__); - if (NULL != child) { - child->state = ORTE_PROC_STATE_UNDEF; + if (NULL != cd->child) { + cd->child->state = ORTE_PROC_STATE_UNDEF; } return rc; } @@ -510,10 +503,10 @@ static int do_parent(orte_proc_t *child, if (NULL == str) { orte_show_help("help-orte-odls-default.txt", "syscall fail", true, - orte_process_info.nodename, app, + orte_process_info.nodename, cd->app->app, "opal_fd_read", __FILE__, __LINE__); - if (NULL != child) { - child->state = ORTE_PROC_STATE_UNDEF; + if (NULL != cd->child) { + cd->child->state = ORTE_PROC_STATE_UNDEF; } return rc; } @@ -534,9 +527,9 @@ static int do_parent(orte_proc_t *child, closed, indicating that the child launched successfully). */ if (msg.fatal) { - if (NULL != child) { - child->state = ORTE_PROC_STATE_FAILED_TO_START; - ORTE_FLAG_UNSET(child, ORTE_PROC_FLAG_ALIVE); + if (NULL != cd->child) { + cd->child->state = ORTE_PROC_STATE_FAILED_TO_START; + ORTE_FLAG_UNSET(cd->child, ORTE_PROC_FLAG_ALIVE); } close(read_fd); return ORTE_ERR_FAILED_TO_START; @@ -546,9 +539,9 @@ static int do_parent(orte_proc_t *child, /* If we got here, it means that the pipe closed without indication of a fatal error, meaning that the child process launched successfully. */ - if (NULL != child) { - child->state = ORTE_PROC_STATE_RUNNING; - ORTE_FLAG_SET(child, ORTE_PROC_FLAG_ALIVE); + if (NULL != cd->child) { + cd->child->state = ORTE_PROC_STATE_RUNNING; + ORTE_FLAG_SET(cd->child, ORTE_PROC_FLAG_ALIVE); } close(read_fd); @@ -559,15 +552,12 @@ static int do_parent(orte_proc_t *child, /** * Fork/exec the specified processes */ -static int odls_default_fork_local_proc(orte_proc_t *child, - char *app, - char **argv, - char **environ_copy, - orte_job_t *jobdat, - orte_iof_base_io_conf_t opts) +static int odls_default_fork_local_proc(void *cdptr) { + orte_odls_spawn_caddy_t *cd = (orte_odls_spawn_caddy_t*)cdptr; int p[2]; pid_t pid; + orte_proc_t *child = cd->child; /* A pipe is used to communicate between the parent and child to indicate whether the exec ultimately succeeded or failed. The @@ -603,12 +593,12 @@ static int odls_default_fork_local_proc(orte_proc_t *child, if (pid == 0) { close(p[0]); - do_child(child, app, argv, environ_copy, jobdat, p[1], opts); + do_child(cd, p[1]); /* Does not return */ } close(p[1]); - return do_parent(child, app, argv, environ_copy, jobdat, p[0], opts); + return do_parent(cd, p[0]); }