Afraid this has a couple of things mixed into the commit. Couldn't be helped - had missed one commit prior to running out the door on vacation.
Fix race conditions in abnormal terminations. We had done a first-cut at this in a prior commit. However, the window remained partially open due to the fact that the HNP has multiple paths leading to orte_finalize. Most of our frameworks don't care if they are finalized more than once, but one of them does, which meant we segfaulted if orte_finalize got called more than once. Besides, we really shouldn't be doing that anyway. So we now introduce a set of atomic locks that prevent us from multiply calling abort, attempting to call orte_finalize, etc. My initial tests indicate this is working cleanly, but since it is a race condition issue, more testing will have to be done before we know for sure that this problem has been licked. Also, some updates relevant to the tool comm library snuck in here. Since those also touched the orted code (as did the prior changes), I didn't want to attempt to separate them out - besides, they are coming in soon anyway. More on them later as that functionality approaches completion. This commit was SVN r17843.
Этот коммит содержится в:
родитель
f443644bfe
Коммит
629b95a2fe
@ -30,6 +30,7 @@
|
||||
#include "orte/runtime/runtime.h"
|
||||
#include "orte/runtime/orte_globals.h"
|
||||
#include "orte/runtime/orte_wakeup.h"
|
||||
#include "orte/runtime/orte_locks.h"
|
||||
#include "orte/mca/plm/plm.h"
|
||||
#include "orte/util/session_dir.h"
|
||||
#include "orte/util/name_fns.h"
|
||||
@ -52,7 +53,7 @@ void orte_errmgr_default_proc_aborted(orte_process_name_t *name, int exit_code)
|
||||
OPAL_TRACE(1);
|
||||
|
||||
/* if we are already in progress, then ignore this call */
|
||||
if (orte_abort_in_progress) {
|
||||
if (!opal_atomic_trylock(&orte_abort_inprogress_lock)) { /* returns 1 if already locked */
|
||||
OPAL_OUTPUT_VERBOSE((1, orte_errmgr_base_output,
|
||||
"%s errmgr:default: abort in progress, ignoring proc %s aborted with status %d",
|
||||
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
|
||||
@ -66,9 +67,6 @@ void orte_errmgr_default_proc_aborted(orte_process_name_t *name, int exit_code)
|
||||
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
|
||||
ORTE_NAME_PRINT(name), exit_code));
|
||||
|
||||
/* flag that we are aborting */
|
||||
orte_abort_in_progress = true;
|
||||
|
||||
/* indicate that all jobs other than the one containing this
|
||||
* proc have been orted to abort - this is necessary to avoid
|
||||
* duplicate ordering of "abort".
|
||||
@ -114,24 +112,20 @@ void orte_errmgr_default_incomplete_start(orte_jobid_t job, int exit_code)
|
||||
OPAL_TRACE(1);
|
||||
|
||||
/* if we are already in progress, then ignore this call */
|
||||
if (orte_abort_in_progress) {
|
||||
if (!opal_atomic_trylock(&orte_abort_inprogress_lock)) { /* returns 1 if already locked */
|
||||
OPAL_OUTPUT_VERBOSE((1, orte_errmgr_base_output,
|
||||
"%s errmgr:default: abort in progress, ignoring incomplete start on job %s with status %d",
|
||||
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
|
||||
ORTE_JOBID_PRINT(job), exit_code));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
OPAL_OUTPUT_VERBOSE((1, orte_errmgr_base_output,
|
||||
"%s errmgr:default: job %s reported incomplete start with status %d",
|
||||
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
|
||||
ORTE_JOBID_PRINT(job), exit_code));
|
||||
|
||||
/* flag that we are aborting */
|
||||
orte_abort_in_progress = true;
|
||||
|
||||
/* tell the plm to terminate all job */
|
||||
/* tell the plm to terminate all jobs */
|
||||
if (ORTE_SUCCESS != (rc = orte_plm.terminate_job(ORTE_JOBID_WILDCARD))) {
|
||||
ORTE_ERROR_LOG(rc);
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ static int xcast(orte_jobid_t job,
|
||||
(long)orte_grpcomm_basic.xcast_linear_xover,
|
||||
(long)orte_grpcomm_basic.xcast_binomial_xover));
|
||||
|
||||
if (orte_process_info.num_procs < 2 || orte_daemon_died) {
|
||||
if (orte_process_info.num_procs < 2 || orte_abnormal_term_ordered) {
|
||||
/* if there is only one proc in the system, then we must
|
||||
* use the direct mode - there is no other option. Note that
|
||||
* since the HNP is the one that typically does xcast sends,
|
||||
|
@ -53,6 +53,7 @@ typedef uint8_t orte_daemon_cmd_flag_t;
|
||||
#define ORTE_DAEMON_DETACH_STDERR_CMD (orte_daemon_cmd_flag_t) 17
|
||||
#define ORTE_DAEMON_SPAWN_JOB_CMD (orte_daemon_cmd_flag_t) 18
|
||||
#define ORTE_DAEMON_TERMINATE_JOB_CMD (orte_daemon_cmd_flag_t) 19
|
||||
#define ORTE_DAEMON_HALT_VM_CMD (orte_daemon_cmd_flag_t) 20
|
||||
|
||||
END_C_DECLS
|
||||
|
||||
|
@ -212,7 +212,7 @@ void orte_plm_base_launch_failed(orte_jobid_t job, bool daemons_launching, pid_t
|
||||
/* set the flag indicating that a daemon failed so we use the proper
|
||||
* methods for attempting to shutdown the rest of the system
|
||||
*/
|
||||
orte_daemon_died = true;
|
||||
orte_abnormal_term_ordered = true;
|
||||
|
||||
}
|
||||
|
||||
@ -767,17 +767,9 @@ void orte_plm_base_check_job_completed(orte_job_t *jdata)
|
||||
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
|
||||
ORTE_JOBID_PRINT(jdata->jobid),
|
||||
ORTE_NAME_PRINT(&(jdata->aborted_proc->name))));
|
||||
/* if we are not already responding to an abort or an abnormal
|
||||
* termination, report this to the errmgr
|
||||
*/
|
||||
if (!orte_abnormal_term_ordered && !orte_abort_in_progress) {
|
||||
orte_errmgr.incomplete_start(jdata->jobid, jdata->aborted_proc->exit_code);
|
||||
} else {
|
||||
/* otherwise, we need to check to see if the jobs are completed
|
||||
* so that we can continue to close down the job
|
||||
*/
|
||||
goto CHECK_ALL_JOBS;
|
||||
}
|
||||
/* report this to the errmgr - it will protect us from multiple calls */
|
||||
orte_errmgr.incomplete_start(jdata->jobid, jdata->aborted_proc->exit_code);
|
||||
goto CHECK_ALL_JOBS;
|
||||
} else if (ORTE_JOB_STATE_ABORTED == jdata->state ||
|
||||
ORTE_JOB_STATE_ABORTED_BY_SIG == jdata->state) {
|
||||
OPAL_OUTPUT_VERBOSE((5, orte_plm_globals.output,
|
||||
@ -785,17 +777,9 @@ void orte_plm_base_check_job_completed(orte_job_t *jdata)
|
||||
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
|
||||
ORTE_JOBID_PRINT(jdata->jobid),
|
||||
ORTE_NAME_PRINT(&(jdata->aborted_proc->name))));
|
||||
/* if we are not already responding to an abort or an abnormal
|
||||
* termination, report this to the errmgr
|
||||
*/
|
||||
if (!orte_abnormal_term_ordered && !orte_abort_in_progress) {
|
||||
orte_errmgr.proc_aborted(&(jdata->aborted_proc->name), jdata->aborted_proc->exit_code);
|
||||
} else {
|
||||
/* otherwise, we need to check to see if the jobs are completed
|
||||
* so that we can continue to close down the job
|
||||
*/
|
||||
goto CHECK_ALL_JOBS;
|
||||
}
|
||||
/* report this to the errmgr */
|
||||
orte_errmgr.proc_aborted(&(jdata->aborted_proc->name), jdata->aborted_proc->exit_code);
|
||||
goto CHECK_ALL_JOBS;
|
||||
} else if (jdata->num_terminated >= jdata->num_procs) {
|
||||
/* this job has terminated - now we need to check to see if ALL
|
||||
* the other jobs have also completed and wakeup if that is true
|
||||
@ -805,6 +789,7 @@ void orte_plm_base_check_job_completed(orte_job_t *jdata)
|
||||
"%s plm:base:check_job_completed declared job %s normally terminated - checking all jobs",
|
||||
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
|
||||
ORTE_JOBID_PRINT(jdata->jobid)));
|
||||
|
||||
CHECK_ALL_JOBS:
|
||||
/* if the job that is being checked is the HNP, then we are
|
||||
* trying to terminate the orteds. In that situation, we
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "orte/runtime/orte_globals.h"
|
||||
#include "orte/util/name_fns.h"
|
||||
#include "orte/runtime/orte_wait.h"
|
||||
#include "orte/orted/orted.h"
|
||||
|
||||
#include "orte/mca/plm/base/base.h"
|
||||
#include "orte/mca/plm/base/plm_private.h"
|
||||
@ -145,12 +146,22 @@ int orte_plm_base_orted_exit(void)
|
||||
ORTE_DETECT_TIMEOUT(&ev, orte_process_info.num_procs,
|
||||
orte_timeout_usec_per_proc,
|
||||
orte_max_timeout, failed_send);
|
||||
/* if I am the HNP, I need to get this message too, but just set things
|
||||
* up so the cmd processor gets called.
|
||||
* We don't want to message ourselves as this can create circular logic
|
||||
* in the RML. Instead, this macro will set a zero-time event which will
|
||||
* cause the buffer to be processed by the cmd processor - probably will
|
||||
* fire right away, but that's okay
|
||||
* The macro makes a copy of the buffer, so it's okay to release it here
|
||||
*/
|
||||
if (orte_process_info.hnp) {
|
||||
ORTE_MESSAGE_EVENT(ORTE_PROC_MY_NAME, &cmd, ORTE_RML_TAG_DAEMON, orte_daemon_cmd_processor);
|
||||
}
|
||||
|
||||
/* now send the command one daemon at a time using a non-blocking
|
||||
* send - let the callback function keep track of how many
|
||||
* complete - it will delete the event if they all do.
|
||||
* Start with vpid=1 since the HNP is always 0 and
|
||||
* it will exit on its own
|
||||
* Start with vpid=1 as the HNP gets it another way
|
||||
*/
|
||||
done_reporting = false;
|
||||
num_reported = 0;
|
||||
@ -238,22 +249,34 @@ int orte_plm_base_orted_kill_local_procs(orte_jobid_t job)
|
||||
orte_timeout_usec_per_proc,
|
||||
orte_max_timeout, failed_send);
|
||||
|
||||
/* if I am the HNP, I need to get this message too, but just set things
|
||||
* up so the cmd processor gets called.
|
||||
* We don't want to message ourselves as this can create circular logic
|
||||
* in the RML. Instead, this macro will set a zero-time event which will
|
||||
* cause the buffer to be processed by the cmd processor - probably will
|
||||
* fire right away, but that's okay
|
||||
* The macro makes a copy of the buffer, so it's okay to release it here
|
||||
*/
|
||||
if (orte_process_info.hnp) {
|
||||
ORTE_MESSAGE_EVENT(ORTE_PROC_MY_NAME, &cmd, ORTE_RML_TAG_DAEMON, orte_daemon_cmd_processor);
|
||||
}
|
||||
|
||||
/* now send the command one daemon at a time using a non-blocking
|
||||
* send - let the callback function keep track of how many
|
||||
* complete - it will delete the event if they all do.
|
||||
* Start with vpid=0 so we get it too
|
||||
* Start with vpid=1 as the HNP gets it another way
|
||||
*/
|
||||
done_reporting = false;
|
||||
num_reported = 0;
|
||||
num_being_sent = orte_process_info.num_procs;
|
||||
num_being_sent = orte_process_info.num_procs-1;
|
||||
peer.jobid = ORTE_PROC_MY_NAME->jobid;
|
||||
for(v=0; v < orte_process_info.num_procs; v++) {
|
||||
for(v=1; v < orte_process_info.num_procs; v++) {
|
||||
peer.vpid = v;
|
||||
/* don't worry about errors on the send here - just
|
||||
* issue it and keep going
|
||||
*/
|
||||
orte_rml.send_buffer_nb(&peer, &cmd, ORTE_RML_TAG_DAEMON, 0,
|
||||
send_callback, 0);
|
||||
send_callback, 0);
|
||||
}
|
||||
/* wait for completion or timeout */
|
||||
while (!done_reporting) {
|
||||
|
@ -283,6 +283,7 @@ static int process_commands(orte_process_name_t* sender,
|
||||
char *contact_info;
|
||||
opal_buffer_t *answer;
|
||||
orte_rml_cmd_flag_t rml_cmd;
|
||||
orte_job_t *jdata;
|
||||
|
||||
/* unpack the command */
|
||||
n = 1;
|
||||
@ -428,7 +429,7 @@ static int process_commands(orte_process_name_t* sender,
|
||||
/**** EXIT COMMAND ****/
|
||||
case ORTE_DAEMON_EXIT_CMD:
|
||||
if (orte_process_info.hnp) {
|
||||
/* if we are mpirun, do nothing - we will
|
||||
/* if we are the HNP, do nothing - we will
|
||||
* exit at our own sweet time
|
||||
*/
|
||||
return ORTE_SUCCESS;
|
||||
@ -449,6 +450,60 @@ static int process_commands(orte_process_name_t* sender,
|
||||
return ORTE_SUCCESS;
|
||||
break;
|
||||
|
||||
/**** HALT VM COMMAND ****/
|
||||
case ORTE_DAEMON_HALT_VM_CMD:
|
||||
if (orte_debug_daemons_flag) {
|
||||
opal_output(0, "%s orted_cmd: received halt vm",
|
||||
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME));
|
||||
}
|
||||
/* trigger our appropriate exit procedure
|
||||
* NOTE: this event will fire -after- any zero-time events
|
||||
* so any pending relays -do- get sent first
|
||||
*/
|
||||
orte_wakeup(0);
|
||||
return ORTE_SUCCESS;
|
||||
break;
|
||||
|
||||
/**** SPAWN JOB COMMAND ****/
|
||||
case ORTE_DAEMON_SPAWN_JOB_CMD:
|
||||
if (orte_debug_daemons_flag) {
|
||||
opal_output(0, "%s orted_cmd: received spawn job",
|
||||
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME));
|
||||
}
|
||||
answer = OBJ_NEW(opal_buffer_t);
|
||||
job = ORTE_JOBID_INVALID;
|
||||
/* can only process this if we are the HNP */
|
||||
if (orte_process_info.hnp) {
|
||||
/* unpack the job data */
|
||||
n = 1;
|
||||
if (ORTE_SUCCESS != (ret = opal_dss.unpack(buffer, &jdata, &n, ORTE_JOB))) {
|
||||
ORTE_ERROR_LOG(ret);
|
||||
goto ANSWER_LAUNCH;
|
||||
}
|
||||
|
||||
/* launch it */
|
||||
if (ORTE_SUCCESS != (ret = orte_plm.spawn(jdata))) {
|
||||
ORTE_ERROR_LOG(ret);
|
||||
goto ANSWER_LAUNCH;
|
||||
}
|
||||
job = jdata->jobid;
|
||||
}
|
||||
ANSWER_LAUNCH:
|
||||
/* pack the jobid to be returned */
|
||||
if (ORTE_SUCCESS != (ret = opal_dss.pack(answer, &job, 1, ORTE_JOBID))) {
|
||||
ORTE_ERROR_LOG(ret);
|
||||
OBJ_RELEASE(answer);
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* return response */
|
||||
if (0 > orte_rml.send_buffer_nb(sender, answer, ORTE_RML_TAG_TOOL, 0,
|
||||
send_callback, NULL)) {
|
||||
ORTE_ERROR_LOG(ORTE_ERR_COMM_FAILURE);
|
||||
ret = ORTE_ERR_COMM_FAILURE;
|
||||
}
|
||||
return ORTE_SUCCESS;
|
||||
break;
|
||||
|
||||
/**** CONTACT QUERY COMMAND ****/
|
||||
case ORTE_DAEMON_CONTACT_QUERY_CMD:
|
||||
if (orte_debug_daemons_flag) {
|
||||
@ -477,7 +532,6 @@ static int process_commands(orte_process_name_t* sender,
|
||||
ORTE_ERROR_LOG(ORTE_ERR_COMM_FAILURE);
|
||||
ret = ORTE_ERR_COMM_FAILURE;
|
||||
}
|
||||
OBJ_RELEASE(answer);
|
||||
break;
|
||||
|
||||
/**** REPORT_JOB_INFO_CMD COMMAND ****/
|
||||
|
@ -60,6 +60,7 @@
|
||||
#include "orte/util/proc_info.h"
|
||||
#include "orte/util/session_dir.h"
|
||||
#include "orte/util/name_fns.h"
|
||||
#include "orte/runtime/orte_locks.h"
|
||||
|
||||
#include "orte/mca/errmgr/errmgr.h"
|
||||
#include "orte/mca/rml/rml.h"
|
||||
@ -566,6 +567,11 @@ static void shutdown_callback(int fd, short flags, void *arg)
|
||||
orte_plm_cmd_flag_t cmd = ORTE_PLM_UPDATE_PROC_STATE;
|
||||
int ret;
|
||||
|
||||
/* protect against multiple calls */
|
||||
if (!opal_atomic_trylock(&orted_exit_lock)) { /* returns 1 if already locked */
|
||||
return;
|
||||
}
|
||||
|
||||
if (NULL != arg) {
|
||||
/* it's the singleton pipe... remove that handler */
|
||||
opal_event_del(&pipe_handler);
|
||||
|
@ -24,6 +24,7 @@ dist_pkgdata_DATA += runtime/help-orte-runtime.txt
|
||||
headers += \
|
||||
runtime/orte_wait.h \
|
||||
runtime/orte_wakeup.h \
|
||||
runtime/orte_locks.h \
|
||||
runtime/runtime.h \
|
||||
runtime/orte_globals.h \
|
||||
runtime/orte_globals_class_instances.h \
|
||||
@ -44,5 +45,6 @@ libopen_rte_la_SOURCES += \
|
||||
runtime/data_type_support/orte_dt_unpacking_fns.c \
|
||||
runtime/orte_wait.c \
|
||||
runtime/orte_wakeup.c \
|
||||
runtime/orte_locks.c \
|
||||
runtime/orte_cr.c \
|
||||
runtime/orte_data_server.c
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "orte/mca/ess/base/base.h"
|
||||
#include "orte/runtime/orte_globals.h"
|
||||
#include "orte/runtime/runtime.h"
|
||||
#include "orte/runtime/orte_locks.h"
|
||||
|
||||
/**
|
||||
* Leave ORTE.
|
||||
@ -42,6 +43,11 @@ int orte_finalize(void)
|
||||
return ORTE_SUCCESS;
|
||||
}
|
||||
|
||||
/* protect against multiple calls */
|
||||
if (!opal_atomic_trylock(&orte_finalize_lock)) { /* returns 1 if already locked */
|
||||
return ORTE_SUCCESS;
|
||||
}
|
||||
|
||||
/* call the finalize function for this environment */
|
||||
orte_ess.finalize();
|
||||
|
||||
|
@ -47,14 +47,11 @@ bool orte_timing;
|
||||
bool orte_debug_flag, orte_debug_daemons_flag, orte_debug_daemons_file_flag;
|
||||
bool orted_spin_flag;
|
||||
int orte_debug_output = -1;
|
||||
bool orte_daemon_died = false;
|
||||
char **orte_launch_environ;
|
||||
char **orted_cmd_line=NULL;
|
||||
int orte_exit, orteds_exit;
|
||||
int orte_exit_status = 0;
|
||||
bool orte_abnormal_term_ordered = false;
|
||||
bool orte_wakeup_ordered = false;
|
||||
bool orte_abort_in_progress = false;
|
||||
int orte_timeout_usec_per_proc;
|
||||
float orte_max_timeout;
|
||||
char *orte_default_hostfile;
|
||||
|
@ -291,15 +291,12 @@ ORTE_DECLSPEC extern bool orted_spin_flag;
|
||||
|
||||
ORTE_DECLSPEC extern int orte_debug_output;
|
||||
|
||||
ORTE_DECLSPEC extern bool orte_daemon_died;
|
||||
|
||||
ORTE_DECLSPEC extern char **orte_launch_environ;
|
||||
ORTE_DECLSPEC extern char **orted_cmd_line;
|
||||
ORTE_DECLSPEC extern int orte_exit, orteds_exit;
|
||||
ORTE_DECLSPEC extern int orte_exit_status;
|
||||
ORTE_DECLSPEC extern bool orte_abnormal_term_ordered;
|
||||
ORTE_DECLSPEC extern bool orte_abort_in_progress;
|
||||
ORTE_DECLSPEC extern bool orte_wakeup_ordered;
|
||||
|
||||
ORTE_DECLSPEC extern int orte_timeout_usec_per_proc;
|
||||
ORTE_DECLSPEC extern float orte_max_timeout;
|
||||
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "orte/runtime/runtime.h"
|
||||
#include "orte/runtime/orte_wait.h"
|
||||
#include "orte/runtime/orte_globals.h"
|
||||
#include "orte/runtime/orte_locks.h"
|
||||
|
||||
#include "orte/runtime/orte_cr.h"
|
||||
|
||||
@ -74,6 +75,12 @@ int orte_init(char flags)
|
||||
/* register handler for errnum -> string conversion */
|
||||
opal_error_register("ORTE", ORTE_ERR_BASE, ORTE_ERR_MAX, orte_err2str);
|
||||
|
||||
/* setup the locks */
|
||||
if (ORTE_SUCCESS != (ret = orte_locks_init())) {
|
||||
error = "orte_locks_init";
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Register all MCA Params */
|
||||
if (ORTE_SUCCESS != (ret = orte_register_params())) {
|
||||
error = "orte_register_params";
|
||||
|
53
orte/runtime/orte_locks.c
Обычный файл
53
orte/runtime/orte_locks.c
Обычный файл
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
* University Research and Technology
|
||||
* Corporation. All rights reserved.
|
||||
* Copyright (c) 2004-2005 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
||||
* University of Stuttgart. All rights reserved.
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*
|
||||
*/
|
||||
|
||||
#include "orte_config.h"
|
||||
#include "orte/constants.h"
|
||||
|
||||
#include "orte/runtime/orte_locks.h"
|
||||
|
||||
/* for everyone */
|
||||
opal_atomic_lock_t orte_finalize_lock;
|
||||
|
||||
/* for orteds */
|
||||
opal_atomic_lock_t orted_exit_lock;
|
||||
|
||||
/* for HNPs */
|
||||
opal_atomic_lock_t orte_wakeup_lock;
|
||||
opal_atomic_lock_t orte_job_complete_lock;
|
||||
opal_atomic_lock_t orte_terminate_lock;
|
||||
opal_atomic_lock_t orte_abort_inprogress_lock;
|
||||
|
||||
|
||||
int orte_locks_init(void)
|
||||
{
|
||||
/* for everyone */
|
||||
opal_atomic_init(&orte_finalize_lock, OPAL_ATOMIC_UNLOCKED);
|
||||
|
||||
/* for orteds */
|
||||
opal_atomic_init(&orted_exit_lock, OPAL_ATOMIC_UNLOCKED);
|
||||
|
||||
/* for HNPs */
|
||||
opal_atomic_init(&orte_wakeup_lock, OPAL_ATOMIC_UNLOCKED);
|
||||
opal_atomic_init(&orte_job_complete_lock, OPAL_ATOMIC_UNLOCKED);
|
||||
opal_atomic_init(&orte_terminate_lock, OPAL_ATOMIC_UNLOCKED);
|
||||
opal_atomic_init(&orte_abort_inprogress_lock, OPAL_ATOMIC_UNLOCKED);
|
||||
|
||||
return ORTE_SUCCESS;
|
||||
}
|
54
orte/runtime/orte_locks.h
Обычный файл
54
orte/runtime/orte_locks.h
Обычный файл
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
* University Research and Technology
|
||||
* Corporation. All rights reserved.
|
||||
* Copyright (c) 2004-2006 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
||||
* University of Stuttgart. All rights reserved.
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Locks to prevent loops inside ORTE
|
||||
*/
|
||||
#ifndef ORTE_LOCKS_H
|
||||
#define ORTE_LOCKS_H
|
||||
|
||||
#include "orte_config.h"
|
||||
#include "orte/types.h"
|
||||
|
||||
#include "opal/sys/atomic.h"
|
||||
|
||||
BEGIN_C_DECLS
|
||||
|
||||
/* for everyone */
|
||||
extern opal_atomic_lock_t orte_finalize_lock;
|
||||
|
||||
/* for orteds */
|
||||
extern opal_atomic_lock_t orted_exit_lock;
|
||||
|
||||
/* for HNPs */
|
||||
extern opal_atomic_lock_t orte_wakeup_lock;
|
||||
extern opal_atomic_lock_t orte_job_complete_lock;
|
||||
extern opal_atomic_lock_t orte_terminate_lock;
|
||||
extern opal_atomic_lock_t orte_abort_inprogress_lock;
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the locks
|
||||
*/
|
||||
ORTE_DECLSPEC int orte_locks_init(void);
|
||||
|
||||
END_C_DECLS
|
||||
|
||||
#endif /* #ifndef ORTE_LOCKS_H */
|
@ -31,6 +31,7 @@
|
||||
#include "orte/runtime/orte_globals.h"
|
||||
#include "orte/util/name_fns.h"
|
||||
#include "orte/runtime/orte_wait.h"
|
||||
#include "orte/runtime/orte_locks.h"
|
||||
|
||||
#include "orte/runtime/orte_wakeup.h"
|
||||
|
||||
@ -39,11 +40,10 @@ int orte_wakeup(int exit_status)
|
||||
/* set the exit status and trigger the
|
||||
* exit procedure
|
||||
*/
|
||||
if (orte_wakeup_ordered) {
|
||||
/* only do this once! */
|
||||
if (!opal_atomic_trylock(&orte_wakeup_lock)) { /* returns 1 if already locked */
|
||||
return ORTE_SUCCESS;
|
||||
}
|
||||
orte_wakeup_ordered = true;
|
||||
|
||||
orte_exit_status = exit_status;
|
||||
orte_trigger_event(orte_exit);
|
||||
return ORTE_SUCCESS;
|
||||
|
@ -1,4 +1,4 @@
|
||||
PROGS = no_op sigusr_trap spin orte_nodename orte_spawn orte_loop_spawn orte_loop_child orte_abort get_limits orte_ring spawn_child
|
||||
PROGS = no_op sigusr_trap spin orte_nodename orte_spawn orte_loop_spawn orte_loop_child orte_abort get_limits orte_ring spawn_child orte_tool orte_no_op
|
||||
|
||||
all: $(PROGS)
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "orte/util/proc_info.h"
|
||||
#include "orte/util/name_fns.h"
|
||||
#include "orte/runtime/orte_globals.h"
|
||||
#include "orte/mca/errmgr/errmgr.h"
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
@ -40,7 +41,7 @@ int main(int argc, char* argv[])
|
||||
if ((ORTE_PROC_MY_NAME->vpid == 3 ||
|
||||
(orte_process_info.num_procs <= 3 && ORTE_PROC_MY_NAME->vpid == 0))
|
||||
&& i == 9995) {
|
||||
orte_abort(1, true);
|
||||
orte_errmgr.abort(1, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
24
orte/test/system/orte_no_op.c
Обычный файл
24
orte/test/system/orte_no_op.c
Обычный файл
@ -0,0 +1,24 @@
|
||||
/* -*- C -*-
|
||||
*
|
||||
* $HEADER$
|
||||
*
|
||||
* The most basic of applications
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "orte/runtime/runtime.h"
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if (ORTE_SUCCESS != orte_init(ORTE_NON_TOOL)) {
|
||||
fprintf(stderr, "Failed orte_init\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ORTE_SUCCESS != orte_finalize()) {
|
||||
fprintf(stderr, "Failed orte_finalize\n");
|
||||
exit(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
103
orte/test/system/orte_tool.c
Обычный файл
103
orte/test/system/orte_tool.c
Обычный файл
@ -0,0 +1,103 @@
|
||||
/* -*- C -*-
|
||||
*
|
||||
* $HEADER$
|
||||
*
|
||||
* The most basic of MPI applications
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "opal/dss/dss.h"
|
||||
#include "opal/util/opal_getcwd.h"
|
||||
|
||||
#include "orte/mca/errmgr/errmgr.h"
|
||||
#include "orte/util/comm/comm.h"
|
||||
#include "orte/util/hnp_contact.h"
|
||||
#include "orte/runtime/orte_globals.h"
|
||||
#include "orte/runtime/runtime.h"
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int rc=ORTE_SUCCESS;
|
||||
orte_job_t *jdata=NULL, **jobs=NULL;
|
||||
opal_list_t hnp_list;
|
||||
orte_hnp_contact_t *hnp;
|
||||
orte_std_cntr_t num_jobs, i;
|
||||
orte_app_context_t *app;
|
||||
char cwd[OMPI_PATH_MAX];
|
||||
|
||||
if (0 > (rc = orte_init(ORTE_TOOL))) {
|
||||
fprintf(stderr, "orte_tool: couldn't init orte\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
/***************
|
||||
* Initialize
|
||||
***************/
|
||||
OBJ_CONSTRUCT(&hnp_list, opal_list_t);
|
||||
|
||||
/*
|
||||
* Get the directory listing
|
||||
*/
|
||||
if (ORTE_SUCCESS != (rc = orte_list_local_hnps(&hnp_list) ) ) {
|
||||
fprintf(stderr, "orte_tool: couldn't get list of HNP's on this system - error %s\n",
|
||||
ORTE_ERROR_NAME(rc));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* if the list is empty, we can't do anything */
|
||||
if (opal_list_is_empty(&hnp_list)) {
|
||||
fprintf(stderr, "orte_tool: no HNP's were found\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* take first one */
|
||||
hnp = (orte_hnp_contact_t*)opal_list_remove_first(&hnp_list);
|
||||
|
||||
/* create a job */
|
||||
jdata = OBJ_NEW(orte_job_t);
|
||||
|
||||
/* create an app_context for this job */
|
||||
app = OBJ_NEW(orte_app_context_t);
|
||||
/* add the app to the job data */
|
||||
opal_pointer_array_add(jdata->apps, app);
|
||||
jdata->num_apps++;
|
||||
|
||||
/* copy over the name of the executable */
|
||||
app->app = strdup("hostname");
|
||||
/* make sure it is also in argv[0]! */
|
||||
app->argv = (char**)malloc(2 * sizeof(char*));
|
||||
app->argv[0] = strdup(app->app);
|
||||
/* record the number of procs to be generated */
|
||||
app->num_procs = 1;
|
||||
/* setup the wd */
|
||||
opal_getcwd(cwd, OMPI_PATH_MAX);
|
||||
app->cwd = strdup(cwd);
|
||||
|
||||
/* spawn it */
|
||||
if (ORTE_SUCCESS != (rc = orte_util_comm_spawn_job(&hnp->name, jdata))) {
|
||||
ORTE_ERROR_LOG(rc);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* report out the jobid */
|
||||
fprintf(stderr, "orte_tool: spawned jobid %s\n", ORTE_JOBID_PRINT(jdata->jobid));
|
||||
#if 0
|
||||
if (ORTE_SUCCESS != (rc = orte_util_comm_query_job_info(&hnp->name, ORTE_JOBID_WILDCARD,
|
||||
&num_jobs, &jobs))) {
|
||||
ORTE_ERROR_LOG(rc);
|
||||
}
|
||||
printf("num jobs: %d\n", num_jobs);
|
||||
opal_dss.dump(0, jobs[0], ORTE_JOB);
|
||||
#endif
|
||||
|
||||
cleanup:
|
||||
if (NULL != jdata) OBJ_RELEASE(jdata);
|
||||
if (NULL != jobs) {
|
||||
for (i=0; i < num_jobs; i++) OBJ_RELEASE(jobs[i]);
|
||||
if (NULL != jobs) free(jobs);
|
||||
}
|
||||
orte_finalize();
|
||||
return rc;
|
||||
}
|
@ -85,6 +85,7 @@
|
||||
#include "orte/runtime/orte_wait.h"
|
||||
#include "orte/runtime/orte_wakeup.h"
|
||||
#include "orte/runtime/orte_data_server.h"
|
||||
#include "orte/runtime/orte_locks.h"
|
||||
|
||||
/* ensure I can behave like a daemon */
|
||||
#include "orte/orted/orted.h"
|
||||
@ -112,7 +113,6 @@ static orte_std_cntr_t total_num_apps = 0;
|
||||
static bool want_prefix_by_default = (bool) ORTE_WANT_ORTERUN_PREFIX_BY_DEFAULT;
|
||||
static opal_event_t *orterun_event, *orteds_exit_event;
|
||||
static char *ompi_server=NULL;
|
||||
static opal_atomic_lock_t terminating;
|
||||
|
||||
/*
|
||||
* Globals
|
||||
@ -312,9 +312,6 @@ int orterun(int argc, char *argv[])
|
||||
int rc;
|
||||
opal_cmd_line_t cmd_line;
|
||||
|
||||
/* initialize the terminating lock */
|
||||
opal_atomic_init(&terminating, OPAL_ATOMIC_UNLOCKED);
|
||||
|
||||
/* find our basename (the name of the executable) so that we can
|
||||
use it in pretty-print error messages */
|
||||
orterun_basename = opal_basename(argv[0]);
|
||||
@ -553,7 +550,12 @@ static void job_completed(int trigpipe, short event, void *arg)
|
||||
int rc;
|
||||
orte_job_state_t exit_state;
|
||||
|
||||
/* close the trigger pipe so it cannot be called again */
|
||||
/* flag that we are here to avoid doing it twice */
|
||||
if (!opal_atomic_trylock(&orte_job_complete_lock)) { /* returns 1 if already locked */
|
||||
return;
|
||||
}
|
||||
|
||||
/* close the trigger pipe */
|
||||
if (0 <= trigpipe) {
|
||||
close(trigpipe);
|
||||
}
|
||||
@ -642,7 +644,7 @@ static void terminated(int trigpipe, short event, void *arg)
|
||||
orte_vpid_t i;
|
||||
|
||||
/* flag that we are here to avoid doing it twice */
|
||||
if (!opal_atomic_trylock(&terminating)) { /* returns 1 if already locked */
|
||||
if (!opal_atomic_trylock(&orte_terminate_lock)) { /* returns 1 if already locked */
|
||||
return;
|
||||
}
|
||||
|
||||
@ -858,11 +860,6 @@ static void abort_exit_callback(int fd, short ign, void *arg)
|
||||
int ret;
|
||||
opal_event_t *event;
|
||||
|
||||
if (orte_abort_in_progress) {
|
||||
/* we are already aborting - just leave it alone */
|
||||
return;
|
||||
}
|
||||
|
||||
if (!orterun_globals.quiet){
|
||||
fprintf(stderr, "%s: killing job...\n\n", orterun_basename);
|
||||
}
|
||||
@ -890,9 +887,13 @@ static void abort_exit_callback(int fd, short ign, void *arg)
|
||||
*/
|
||||
ORTE_DETECT_TIMEOUT(&event, jdata->num_procs,
|
||||
orte_timeout_usec_per_proc,
|
||||
orte_max_timeout,
|
||||
orte_max_timeout,
|
||||
timeout_callback);
|
||||
|
||||
|
||||
/* terminate the job - this will wake us up and
|
||||
* call the "terminated" function so we clean up
|
||||
* and exit
|
||||
*/
|
||||
ret = orte_plm.terminate_job(ORTE_JOBID_WILDCARD);
|
||||
if (ORTE_SUCCESS != ret) {
|
||||
/* If we failed the terminate_job() above, then we
|
||||
@ -925,10 +926,11 @@ static void abort_exit_callback(int fd, short ign, void *arg)
|
||||
*/
|
||||
static void abort_signal_callback(int fd, short flags, void *arg)
|
||||
{
|
||||
/* if we have already ordered this once, or we are already
|
||||
* aborting the job, don't keep doing it to avoid race conditions
|
||||
/* if we have already ordered this once, don't keep
|
||||
* doing it to avoid race conditions
|
||||
*/
|
||||
if (orte_abnormal_term_ordered || orte_abort_in_progress) {
|
||||
if (!opal_atomic_trylock(&orte_abort_inprogress_lock)) { /* returns 1 if already locked */
|
||||
fprintf(stderr, "%s: abort is already in progress...\n\n", orterun_basename);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -570,3 +570,38 @@ CLEANUP:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int orte_util_comm_halt_vm(const orte_process_name_t *hnp)
|
||||
{
|
||||
opal_buffer_t buf;
|
||||
orte_daemon_cmd_flag_t command;
|
||||
int rc;
|
||||
|
||||
OPAL_OUTPUT_VERBOSE((5, orte_debug_output,
|
||||
"%s util_comm_halt_vm: ordering HNP %s terminate",
|
||||
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
|
||||
ORTE_NAME_PRINT(hnp)));
|
||||
|
||||
/* setup the buffer */
|
||||
OBJ_CONSTRUCT(&buf, opal_buffer_t);
|
||||
|
||||
/* tell the HNP to die */
|
||||
command = ORTE_DAEMON_HALT_VM_CMD;
|
||||
if (ORTE_SUCCESS != (rc = opal_dss.pack(&buf, &command, 1, ORTE_DAEMON_CMD))) {
|
||||
ORTE_ERROR_LOG(rc);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* send the order */
|
||||
if (0 > (rc = orte_rml.send_buffer((orte_process_name_t*)hnp, &buf, ORTE_RML_TAG_DAEMON, 0))) {
|
||||
ORTE_ERROR_LOG(rc);
|
||||
goto CLEANUP;
|
||||
}
|
||||
OBJ_DESTRUCT(&buf);
|
||||
|
||||
/* don't bother waiting around */
|
||||
CLEANUP:
|
||||
OBJ_DESTRUCT(&buf);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -59,5 +59,7 @@ ORTE_DECLSPEC int orte_util_comm_spawn_job(const orte_process_name_t *hnp, orte_
|
||||
|
||||
ORTE_DECLSPEC int orte_util_comm_terminate_job(const orte_process_name_t *hnp, orte_jobid_t job);
|
||||
|
||||
ORTE_DECLSPEC int orte_util_comm_halt_vm(const orte_process_name_t *hnp);
|
||||
|
||||
END_C_DECLS
|
||||
#endif
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user