/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ /* * Copyright (c) 2004-2010 The Trustees of Indiana University and Indiana * University Research and Technology * Corporation. All rights reserved. * Copyright (c) 2004-2022 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 (c) 2007-2020 Cisco Systems, Inc. All rights reserved * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2009 Oak Ridge National Labs. All rights reserved. * Copyright (c) 2010-2015 Los Alamos National Security, LLC. * All rights reserved. * Copyright (c) 2013-2019 Intel, Inc. All rights reserved. * Copyright (c) 2015-2017 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2017-2022 Amazon.com, Inc. or its affiliates. All Rights reserved. * All Rights reserved. * Copyright (c) 2018 Mellanox Technologies, Inc. * All rights reserved. * Copyright (c) 2018-2019 Triad National Security, LLC. All rights * reserved. * Copyright (c) 2020 FUJITSU LIMITED. All rights reserved. * Copyright (c) 2021 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow * * $HEADER$ */ /** @file **/ #ifdef HAVE_UNISTD_H # include #endif #include "opal/include/opal_config.h" #include "opal/mca/base/base.h" #include "opal/mca/base/mca_base_var.h" #include "opal/mca/hwloc/base/base.h" #include "opal/mca/installdirs/base/base.h" #include "opal/mca/memchecker/base/base.h" #include "opal/mca/memcpy/base/base.h" #include "opal/mca/memory/base/base.h" #include "opal/mca/patcher/base/base.h" #include "opal/mca/pmix/base/base.h" #include "opal/mca/reachable/base/base.h" #include "opal/mca/shmem/base/base.h" #include "opal/mca/smsc/base/base.h" #include "opal/mca/threads/threads.h" #include "opal/mca/threads/tsd.h" #include "opal/mca/timer/base/base.h" #include "opal/memoryhooks/memory.h" #include "opal/runtime/opal.h" #include "opal/util/arch.h" #include "opal/util/malloc.h" #include "opal/util/net.h" #include "opal/util/output.h" #include "opal/util/proc.h" #include "opal/util/show_help.h" #include "opal/mca/backtrace/base/base.h" #include "opal/mca/threads/base/base.h" #include "opal/runtime/opal_progress.h" #include "opal/runtime/opal_params_core.h" #include "opal/util/opal_environ.h" #include "opal/constants.h" #include "opal/util/error.h" #include "opal/util/event.h" #include "opal/util/keyval_parse.h" #include "opal/util/stacktrace.h" #include "opal/util/sys_limits.h" #include "opal/util/timings.h" int opal_util_initialized = 0; bool opal_warn_on_fork = true; int opal_init_error(const char *error, int ret); static int opal_err2str(int errnum, const char **errmsg) { const char *retval; switch (errnum) { case OPAL_SUCCESS: retval = "Success"; break; case OPAL_ERROR: retval = "Error"; break; case OPAL_ERR_OUT_OF_RESOURCE: retval = "Out of resource"; break; case OPAL_ERR_TEMP_OUT_OF_RESOURCE: retval = "Temporarily out of resource"; break; case OPAL_ERR_RESOURCE_BUSY: retval = "Resource busy"; break; case OPAL_ERR_BAD_PARAM: retval = "Bad parameter"; break; case OPAL_ERR_FATAL: retval = "Fatal"; break; case OPAL_ERR_NOT_IMPLEMENTED: retval = "Not implemented"; break; case OPAL_ERR_NOT_SUPPORTED: retval = "Not supported"; break; case OPAL_ERR_INTERRUPTED: retval = "Interrupted"; break; case OPAL_ERR_WOULD_BLOCK: retval = "Would block"; break; case OPAL_ERR_IN_ERRNO: retval = "In errno"; break; case OPAL_ERR_UNREACH: retval = "Unreachable"; break; case OPAL_ERR_NOT_FOUND: retval = "Not found"; break; case OPAL_EXISTS: retval = "Exists"; break; case OPAL_ERR_TIMEOUT: retval = "Timeout"; break; case OPAL_ERR_NOT_AVAILABLE: retval = "Not available"; break; case OPAL_ERR_PERM: retval = "No permission"; break; case OPAL_ERR_VALUE_OUT_OF_BOUNDS: retval = "Value out of bounds"; break; case OPAL_ERR_FILE_READ_FAILURE: retval = "File read failure"; break; case OPAL_ERR_FILE_WRITE_FAILURE: retval = "File write failure"; break; case OPAL_ERR_FILE_OPEN_FAILURE: retval = "File open failure"; break; case OPAL_ERR_PACK_MISMATCH: retval = "Pack data mismatch"; break; case OPAL_ERR_PACK_FAILURE: retval = "Data pack failed"; break; case OPAL_ERR_UNPACK_FAILURE: retval = "Data unpack failed"; break; case OPAL_ERR_UNPACK_INADEQUATE_SPACE: retval = "Data unpack had inadequate space"; break; case OPAL_ERR_UNPACK_READ_PAST_END_OF_BUFFER: retval = "Data unpack would read past end of buffer"; break; case OPAL_ERR_OPERATION_UNSUPPORTED: retval = "Requested operation is not supported on referenced data type"; break; case OPAL_ERR_UNKNOWN_DATA_TYPE: retval = "Unknown data type"; break; case OPAL_ERR_BUFFER: retval = "Buffer type (described vs non-described) mismatch - operation not allowed"; break; case OPAL_ERR_DATA_TYPE_REDEF: retval = "Attempt to redefine an existing data type"; break; case OPAL_ERR_DATA_OVERWRITE_ATTEMPT: retval = "Attempt to overwrite a data value"; break; case OPAL_ERR_MODULE_NOT_FOUND: retval = "Framework requires at least one active module, but none found"; break; case OPAL_ERR_TOPO_SLOT_LIST_NOT_SUPPORTED: retval = "OS topology does not support slot_list process affinity"; break; case OPAL_ERR_TOPO_SOCKET_NOT_SUPPORTED: retval = "Could not obtain socket topology information"; break; case OPAL_ERR_TOPO_CORE_NOT_SUPPORTED: retval = "Could not obtain core topology information"; break; case OPAL_ERR_NOT_ENOUGH_SOCKETS: retval = "Not enough sockets to meet request"; break; case OPAL_ERR_NOT_ENOUGH_CORES: retval = "Not enough cores to meet request"; break; case OPAL_ERR_INVALID_PHYS_CPU: retval = "Invalid physical cpu number returned"; break; case OPAL_ERR_MULTIPLE_AFFINITIES: retval = "Multiple methods for assigning process affinity were specified"; break; case OPAL_ERR_SLOT_LIST_RANGE: retval = "Provided slot_list range is invalid"; break; case OPAL_ERR_NETWORK_NOT_PARSEABLE: retval = "Provided network specification is not parseable"; break; case OPAL_ERR_SILENT: retval = NULL; break; case OPAL_ERR_NOT_INITIALIZED: retval = "Not initialized"; break; case OPAL_ERR_NOT_BOUND: retval = "Not bound"; break; case OPAL_ERR_TAKE_NEXT_OPTION: retval = "Take next option"; break; case OPAL_ERR_PROC_ENTRY_NOT_FOUND: retval = "Database entry not found"; break; case OPAL_ERR_DATA_VALUE_NOT_FOUND: retval = "Data for specified key not found"; break; case OPAL_ERR_CONNECTION_FAILED: retval = "Connection failed"; break; case OPAL_ERR_AUTHENTICATION_FAILED: retval = "Authentication failed"; break; case OPAL_ERR_COMM_FAILURE: retval = "Comm failure"; break; case OPAL_ERR_SERVER_NOT_AVAIL: retval = "Server not available"; break; case OPAL_ERR_IN_PROCESS: retval = "Operation in process"; break; case OPAL_ERR_DEBUGGER_RELEASE: retval = "Release debugger"; break; case OPAL_ERR_HANDLERS_COMPLETE: retval = "Event handlers complete"; break; case OPAL_ERR_PARTIAL_SUCCESS: retval = "Partial success"; break; case OPAL_ERR_PROC_ABORTED: retval = "Process abnormally terminated"; break; case OPAL_ERR_PROC_REQUESTED_ABORT: retval = "Process requested abort"; break; case OPAL_ERR_PROC_ABORTING: retval = "Process is aborting"; break; case OPAL_ERR_NODE_DOWN: retval = "Node has gone down"; break; case OPAL_ERR_NODE_OFFLINE: retval = "Node has gone offline"; break; case OPAL_ERR_JOB_TERMINATED: retval = "Job terminated"; break; case OPAL_ERR_PROC_RESTART: retval = "Process restarted"; break; case OPAL_ERR_PROC_CHECKPOINT: retval = "Process checkpoint"; break; case OPAL_ERR_PROC_MIGRATE: retval = "Process migrate"; break; case OPAL_ERR_EVENT_REGISTRATION: retval = "Event registration"; break; case OPAL_ERR_HEARTBEAT_ALERT: retval = "Heartbeat not received"; break; case OPAL_ERR_FILE_ALERT: retval = "File alert - proc may have stalled"; break; case OPAL_ERR_MODEL_DECLARED: retval = "Model declared"; break; case OPAL_PMIX_LAUNCH_DIRECTIVE: retval = "Launch directive"; break; default: retval = "UNRECOGNIZED"; } *errmsg = retval; return OPAL_SUCCESS; } int opal_init_error(const char *error, int ret) { if (OPAL_ERR_SILENT != ret) { opal_show_help("help-opal-runtime.txt", "opal_init:startup:internal-failure", true, error, ret); } return ret; } /* If there is a preprocessor macro that redefined the call to * gethostname, we undefine that here */ #ifdef gethostname # undef gethostname #endif #define NUM_TRIES_FOR_NULL_HOSTNAME 8 /* * This gethostname wrapper does not return the full-length hostname in * those rare cases where it is too long for the buffer. It does, however, * guarantee a null-terminated hostname is returned, even if it's * truncated. It also tries again in the case where gethostname returns an * error because the buffer is initially too short. */ int opal_init_gethostname(void) { size_t count, length = OPAL_LOCAL_MAXHOSTNAMELEN; int ret_val, num_tries = 0; char *newbuf; char *buf = calloc(1, length); if (NULL == buf) { return OPAL_ERR_OUT_OF_RESOURCE; } while (num_tries < NUM_TRIES_FOR_NULL_HOSTNAME) { ++num_tries; /* * Offer all but the last byte of the buffer to gethostname. */ ret_val = gethostname(buf, length - 1); /* * Terminate the buffer in the last position. */ buf[length - 1] = '\0'; if (0 == ret_val) { count = strlen(buf); /* The result was not truncated */ if (count > 0 && count < length - 1) { /* * If we got a good result, save it. This value may * be longer than what callers to opal_gethostname() * are expecting, so that should be checked by the * caller. */ opal_process_info.nodename = buf; return OPAL_SUCCESS; } /* * "Good" cases: * * 0 == count: The buffer is empty. In some gethostname * implementations, this can be because the * buffer was too small. * (length-1) == count: The result *may* be truncated. * * If it's one of these cases, we'll fall through to * increase the length of the buffer and try again. * * If it's not one of these good cases, it's an error: * return. */ else if (!(0 == count || count == length - 1)) { free(buf); return OPAL_ERR_IN_ERRNO; } } /* * "Good" cases: * * errno == EINVAL or ENAMETOOLONG: hostname was truncated and * there was an error. Perhaps there is something * in the buffer and perhaps not. * * If it's one of these cases, we'll fall through to * increase the length of the buffer and try again. * * If it's not one of these good cases, it's an error: return. */ else if (!(EINVAL == errno || ENAMETOOLONG == errno)) { free(buf); return OPAL_ERR_IN_ERRNO; } /* * If we get here, it means we want to double the length of * the buffer and try again. */ length *= 2; newbuf = realloc(buf, length); if (NULL == newbuf) { free(buf); return OPAL_ERR_OUT_OF_RESOURCE; } buf = newbuf; } /* end while */ /* If we got here, it means that we tried too many times and are * giving up. */ free(buf); return OPAL_ERR_NOT_FOUND; } static mca_base_framework_t *opal_init_util_frameworks[] = { &opal_installdirs_base_framework, NULL, }; int opal_init_util(int *pargc, char ***pargv) { int ret; char *error = NULL; OPAL_TIMING_ENV_INIT(otmng); if (opal_util_initialized != 0) { if (opal_util_initialized < 0) { return OPAL_ERROR; } ++opal_util_initialized; return OPAL_SUCCESS; } OBJ_CONSTRUCT(&opal_init_util_domain, opal_finalize_domain_t); (void) opal_finalize_domain_init(&opal_init_util_domain, "opal_init_util"); opal_finalize_set_domain(&opal_init_util_domain); opal_thread_set_main(); /* set the nodename right away so anyone who needs it has it. Note * that we don't bother with fqdn and prefix issues here - we let * the RTE later replace this with a modified name if the user * requests it */ ret = opal_init_gethostname(); if (OPAL_SUCCESS != ret) { fprintf(stderr, "opal_init_gethostname() failed -- process will likely abort (%s:%d, returned %d " "instead of OPAL_SUCCESS)\n", __FILE__, __LINE__, ret); return ret; } /* initialize the memory allocator */ opal_malloc_init(); OPAL_TIMING_ENV_NEXT(otmng, "opal_malloc_init"); /* initialize the output system */ opal_output_init(); /* initialize install dirs code */ if (OPAL_SUCCESS != (ret = mca_base_framework_open(&opal_installdirs_base_framework, 0))) { fprintf(stderr, "opal_installdirs_base_open() failed -- process will likely abort (%s:%d, returned " "%d instead of OPAL_SUCCESS)\n", __FILE__, __LINE__, ret); return ret; } /* initialize the help system */ opal_show_help_init(); OPAL_TIMING_ENV_NEXT(otmng, "opal_show_help_init"); /* register handler for errnum -> string converstion */ if (OPAL_SUCCESS != (ret = opal_error_register("OPAL", OPAL_ERR_BASE, OPAL_ERR_MAX, opal_err2str))) { return opal_init_error("opal_error_register", ret); } /* keyval lex-based parser */ if (OPAL_SUCCESS != (ret = opal_util_keyval_parse_init())) { return opal_init_error("opal_util_keyval_parse_init", ret); } /* Setup the parameter system */ if (OPAL_SUCCESS != (ret = mca_base_var_init())) { return opal_init_error("mca_base_var_init", ret); } OPAL_TIMING_ENV_NEXT(otmng, "opal_var_init"); /* read any param files that were provided */ if (OPAL_SUCCESS != (ret = mca_base_var_cache_files(false))) { return opal_init_error("failed to cache files", ret); } OPAL_TIMING_ENV_NEXT(otmng, "opal_var_cache"); /* register util params for opal */ if (OPAL_SUCCESS != (ret = opal_register_util_params())) { return opal_init_error("opal_register_util_params", ret); } /* pretty-print stack handlers */ if (OPAL_SUCCESS != (ret = opal_util_register_stackhandlers())) { return opal_init_error("opal_util_register_stackhandlers", ret); } /* set system resource limits - internally protected against * doing so twice in cases where the launch agent did it for us */ if (OPAL_SUCCESS != (ret = opal_util_init_sys_limits(&error))) { opal_show_help("help-opal-runtime.txt", "opal_init:syslimit", false, error); return OPAL_ERR_SILENT; } /* initialize the arch string */ if (OPAL_SUCCESS != (ret = opal_arch_init())) { return opal_init_error("opal_arch_init", ret); } OPAL_TIMING_ENV_NEXT(otmng, "opal_arch_init"); /* initialize the mca */ if (OPAL_SUCCESS != (ret = mca_base_open())) { return opal_init_error("mca_base_open", ret); } OPAL_TIMING_ENV_NEXT(otmng, "mca_base_open"); /* register for cleanup */ opal_finalize_register_cleanup_arg(mca_base_framework_close_list, opal_init_util_frameworks); ++opal_util_initialized; return OPAL_SUCCESS; }