📄 orterun.c
字号:
state = ABORT_SIGNAL_DONE;}/** * Pass user signals to the remote application processes */static void signal_forward_callback(int fd, short event, void *arg){ struct opal_event *signal = (struct opal_event*)arg; int signum, ret; opal_list_t attrs; opal_list_item_t *item; OPAL_TRACE(1); signum = OPAL_EVENT_SIGNAL(signal); if (!orterun_globals.quiet){ fprintf(stderr, "%s: Forwarding signal %d to job", orterun_basename, signum); } /** send the signal out to the processes, including any descendants */ OBJ_CONSTRUCT(&attrs, opal_list_t); orte_rmgr.add_attribute(&attrs, ORTE_NS_INCLUDE_DESCENDANTS, ORTE_UNDEF, NULL, ORTE_RMGR_ATTR_OVERRIDE); if (ORTE_SUCCESS != (ret = orte_pls.signal_job(jobid, signum, &attrs))) { fprintf(stderr, "Signal %d could not be sent to the job (returned %d)", signum, ret); } while (NULL != (item = opal_list_remove_first(&attrs))) OBJ_RELEASE(item); OBJ_DESTRUCT(&attrs);}static int init_globals(void){ /* Only CONSTRUCT things once */ if (!globals_init) { OBJ_CONSTRUCT(&orterun_globals.lock, opal_mutex_t); OBJ_CONSTRUCT(&orterun_globals.cond, opal_condition_t); orterun_globals.hostfile = NULL; orterun_globals.env_val = NULL; orterun_globals.appfile = NULL; orterun_globals.wdir = NULL; orterun_globals.path = NULL; } /* Reset the other fields every time */ orterun_globals.help = false; orterun_globals.version = false; orterun_globals.verbose = false; orterun_globals.quiet = false; orterun_globals.exit = false; orterun_globals.no_wait_for_job_completion = false; orterun_globals.by_node = false; orterun_globals.by_slot = false; orterun_globals.debugger = false; orterun_globals.do_not_launch = false; orterun_globals.num_procs = 0; orterun_globals.exit_status = 0; if( NULL != orterun_globals.hostfile ) free( orterun_globals.hostfile ); orterun_globals.hostfile = NULL; if( NULL != orterun_globals.env_val ) free( orterun_globals.env_val ); orterun_globals.env_val = NULL; if( NULL != orterun_globals.appfile ) free( orterun_globals.appfile ); orterun_globals.appfile = NULL; if( NULL != orterun_globals.wdir ) free( orterun_globals.wdir ); orterun_globals.wdir = NULL; if( NULL != orterun_globals.path ) free( orterun_globals.path ); orterun_globals.path = NULL; /* All done */ globals_init = true; return ORTE_SUCCESS;}static int parse_globals(int argc, char* argv[]){ opal_cmd_line_t cmd_line; int id, ret; /* Setup and parse the command line */ init_globals(); opal_cmd_line_create(&cmd_line, cmd_line_init); mca_base_cmd_line_setup(&cmd_line); if (ORTE_SUCCESS != (ret = opal_cmd_line_parse(&cmd_line, true, argc, argv)) ) { return ret; } /* print version if requested. Do this before check for help so that --version --help works as one might expect. */ if (orterun_globals.version && !(1 == argc || orterun_globals.help)) { char *project_name = NULL; if (0 == strcmp(orterun_basename, "mpirun")) { project_name = "Open MPI"; } else { project_name = "OpenRTE"; } opal_show_help("help-orterun.txt", "orterun:version", false, orterun_basename, project_name, OPAL_VERSION, PACKAGE_BUGREPORT); /* if we were the only argument, exit */ if (2 == argc) exit(0); } /* Check for help request */ if (1 == argc || orterun_globals.help) { char *args = NULL; char *project_name = NULL; if (0 == strcmp(orterun_basename, "mpirun")) { project_name = "Open MPI"; } else { project_name = "OpenRTE"; } args = opal_cmd_line_get_usage_msg(&cmd_line); opal_show_help("help-orterun.txt", "orterun:usage", false, orterun_basename, project_name, OPAL_VERSION, orterun_basename, args, PACKAGE_BUGREPORT); free(args); /* If someone asks for help, that should be all we do */ exit(0); } /* Do we want a user-level debugger? */ if (orterun_globals.debugger) { orte_run_debugger(orterun_basename, &cmd_line, argc, argv); } /* Allocate and map by node or by slot? Shortcut for setting an MCA param. */ /* Don't initialize the MCA parameter here unless we have to, * since it really should be initialized in rmaps_base_open */ if (orterun_globals.by_node || orterun_globals.by_slot) { char *policy = NULL; id = mca_base_param_reg_string_name("rmaps", "base_schedule_policy", "Scheduling policy for RMAPS. [slot | node]", false, false, "slot", &policy); if (orterun_globals.by_node) { orterun_globals.by_slot = false; mca_base_param_set_string(id, "node"); } else { orterun_globals.by_slot = true; mca_base_param_set_string(id, "slot"); } free(policy); } else { /* Default */ orterun_globals.by_slot = true; } /* If we don't want to wait, we don't want to wait */ if (orterun_globals.no_wait_for_job_completion) { wait_for_job_completion = false; } OBJ_DESTRUCT(&cmd_line); return ORTE_SUCCESS;}static int parse_locals(int argc, char* argv[]){ int i, rc, app_num; int temp_argc; char **temp_argv, **env; orte_app_context_t *app; bool made_app; orte_std_cntr_t j, size1; /* Make the apps */ temp_argc = 0; temp_argv = NULL; opal_argv_append(&temp_argc, &temp_argv, argv[0]); /* Make the max size of the array be INT_MAX because we may be parsing an app file, in which case we don't know how many entries there will be. The max size of an orte_pointer_array is only a safety net; it only initially allocates block_size entries (2, in this case) */ orte_pointer_array_init(&apps_pa, 1, INT_MAX, 2); /* NOTE: This bogus env variable is necessary in the calls to create_app(), below. See comment immediately before the create_app() function for an explanation. */ env = NULL; for (app_num = 0, i = 1; i < argc; ++i) { if (0 == strcmp(argv[i], ":")) { /* Make an app with this argv */ if (opal_argv_count(temp_argv) > 1) { if (NULL != env) { opal_argv_free(env); env = NULL; } app = NULL; rc = create_app(temp_argc, temp_argv, &app, &made_app, &env); /** keep track of the number of apps - point this app_context to that index */ if (ORTE_SUCCESS != rc) { /* Assume that the error message has already been printed; no need to cleanup -- we can just exit */ exit(1); } if (made_app) { orte_std_cntr_t dummy; app->idx = app_num; ++app_num; orte_pointer_array_add(&dummy, apps_pa, app); } /* Reset the temps */ temp_argc = 0; temp_argv = NULL; opal_argv_append(&temp_argc, &temp_argv, argv[0]); } } else { opal_argv_append(&temp_argc, &temp_argv, argv[i]); } } if (opal_argv_count(temp_argv) > 1) { app = NULL; rc = create_app(temp_argc, temp_argv, &app, &made_app, &env); if (ORTE_SUCCESS != rc) { /* Assume that the error message has already been printed; no need to cleanup -- we can just exit */ exit(1); } if (made_app) { orte_std_cntr_t dummy; app->idx = app_num; ++app_num; orte_pointer_array_add(&dummy, apps_pa, app); } } if (NULL != env) { opal_argv_free(env); } opal_argv_free(temp_argv); /* Once we've created all the apps, add the global MCA params to each app's environment (checking for duplicates, of course -- yay opal_environ_merge()). */ if (NULL != global_mca_env) { size1 = orte_pointer_array_get_size(apps_pa); /* Iterate through all the apps */ for (j = 0; j < size1; ++j) { app = (orte_app_context_t *) orte_pointer_array_get_item(apps_pa, j); if (NULL != app) { /* Use handy utility function */ env = opal_environ_merge(global_mca_env, app->env); opal_argv_free(app->env); app->env = env; } } } /* Now take a subset of the MCA params and set them as MCA overrides here in orterun (so that when we orte_init() later, all the components see these MCA params). Here's how we decide which subset of the MCA params we set here in orterun: 1. If any global MCA params were set, use those 2. If no global MCA params were set and there was only one app, then use its app MCA params 3. Otherwise, don't set any */ env = NULL; if (NULL != global_mca_env) { env = global_mca_env; } else { if (orte_pointer_array_get_size(apps_pa) >= 1) { /* Remember that pointer_array's can be padded with NULL entries; so only use the app's env if there is exactly 1 non-NULL entry */ app = (orte_app_context_t *) orte_pointer_array_get_item(apps_pa, 0); if (NULL != app) { env = app->env; for (j = 1; j < orte_pointer_array_get_size(apps_pa); ++j) { if (NULL != orte_pointer_array_get_item(apps_pa, j)) { env = NULL; break; } } } } } if (NULL != env) { size1 = opal_argv_count(env); for (j = 0; j < size1; ++j) { putenv(env[j]); } } /* All done */ return ORTE_SUCCESS;}/* * This function takes a "char ***app_env" parameter to handle the * specific case: * * orterun --mca foo bar -app appfile * * That is, we'll need to keep foo=bar, but the presence of the app * file will cause an invocation of parse_appfile(), which will cause * one or more recursive calls back to create_app(). Since the * foo=bar value applies globally to all apps in the appfile, we need * to pass in the "base" environment (that contains the foo=bar value) * when we parse each line in the appfile. * * This is really just a special case -- when we have a simple case like: * * orterun --mca foo bar -np 4 hostname * * Then the upper-level function (parse_locals()) calls create_app() * with a NULL value for app_env, meaning that there is no "base" * environment that the app needs to be created from. */static int create_app(int argc, char* argv[], orte_app_context_t **app_ptr, bool *made_app, char ***app_env){ opal_cmd_line_t cmd_line; char cwd[OMPI_PATH_MAX]; int i, j, count, rc; char *param, *value, *value2; orte_app_context_t *app = NULL;#if 0 /* Used only in the C/N notion case, remove to silence compiler warnings */ orte_std_cntr_t l, len;#endif bool map_data = false, save_arg, cmd_line_made = false; int new_argc = 0; char **new_argv = NULL; *made_app = false; /* Pre-process the command line: - convert C, cX, N, nX arguments to "-rawmap <id> <arg>" so that the parser can pick it up nicely. - convert -host to -rawmap <id> <arg> - convert -arch to -rawmap <id> <arg> Converting these to the same argument type will a) simplify the logic down below, and b) allow us to preserve the ordering of these arguments as the user specified them on the command line. */ for (i = 0; i < argc; ++i) { map_data = false; save_arg = true; /* JJH To fix in the future * Currently C/N notation is not supported so don't execute this check * Bug: Make this context sensitive since it will not behave properly * with the following argument set: * $ orterun -np 2 -host c2,c3,c12 hostname * Since it will see the hosts c2, c3, and c12 as C options instead * of hostnames. */ if(false) { ; } /* Wrapper to preserve logic continuation while the below is commented out */#if 0 if (0 == strcmp(argv[i], "C") || 0 == strcmp(argv[i], "N")) { map_data = true; } /* Heuristic: if the string fits "[cn][0-9]+" or "[cn][0-9],", then accept it as mapping data */ else if ('c' == argv[i][0] || 'n' == argv[i][0]) { len = strlen(argv[i]); if (len > 1) { for (l = 1; l < len; ++l) { if (',' == argv[i][l]) { map_data = true; break; } else if (!isdigit(argv[i][l])) { break; } } if (l >= len) { map_data = true; } } }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -