Skip to content

Commit 102d864

Browse files
Fix /tmp approach, and add environment variable method as third fallback during library registration
The /tmp fallback for /dev/shm did not write to a fixed filename, so multiple instances of the runtime would not be able to detect each other. Now, we create the /tmp file in much the same way as the /dev/shm file was created, since mkstemp approach would not work to create a file that other instances of the runtime would detect. Also, add the environment variable method as a third fallback to /dev/shm and /tmp for library registration, as some systems do not have either. Also, add ability to fallback to a subsequent method should a failure occur during any part of the registration process. When unregistering, it is assumed that the method chosen during registration should work, so errors at that point are ignored. This also avoids a problem with multiple threads trying to unregister the library.
1 parent 098f46d commit 102d864

File tree

3 files changed

+164
-73
lines changed

3 files changed

+164
-73
lines changed

openmp/runtime/src/kmp.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3620,6 +3620,9 @@ extern void __kmp_warn(char const *format, ...);
36203620

36213621
extern void __kmp_set_num_threads(int new_nth, int gtid);
36223622

3623+
extern bool __kmp_detect_shm();
3624+
extern bool __kmp_detect_tmp();
3625+
36233626
// Returns current thread (pointer to kmp_info_t). Current thread *must* be
36243627
// registered.
36253628
static inline kmp_info_t *__kmp_entry_thread() {

openmp/runtime/src/kmp_runtime.cpp

Lines changed: 137 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -6717,6 +6717,8 @@ static inline char *__kmp_reg_status_name() {
67176717
} // __kmp_reg_status_get
67186718

67196719
#if defined(KMP_USE_SHM)
6720+
bool __kmp_shm_available = false;
6721+
bool __kmp_tmp_available = false;
67206722
// If /dev/shm is not accessible, we will create a temporary file under /tmp.
67216723
char *temp_reg_status_file_name = nullptr;
67226724
#endif
@@ -6746,60 +6748,108 @@ void __kmp_register_library_startup(void) {
67466748
char *value = NULL; // Actual value of the environment variable.
67476749

67486750
#if defined(KMP_USE_SHM)
6749-
char *shm_name = __kmp_str_format("/%s", name);
6750-
int shm_preexist = 0;
6751-
char *data1;
6752-
int fd1 = shm_open(shm_name, O_CREAT | O_EXCL | O_RDWR, 0666);
6753-
if ((fd1 == -1) && (errno == EEXIST)) {
6754-
// file didn't open because it already exists.
6755-
// try opening existing file
6756-
fd1 = shm_open(shm_name, O_RDWR, 0666);
6757-
if (fd1 == -1) { // file didn't open
6758-
// error out here
6759-
__kmp_fatal(KMP_MSG(FunctionError, "Can't open SHM"), KMP_ERR(0),
6760-
__kmp_msg_null);
6761-
} else {
6762-
// able to open existing file
6763-
shm_preexist = 1;
6751+
char *shm_name = nullptr;
6752+
char *data1 = nullptr;
6753+
__kmp_shm_available = __kmp_detect_shm();
6754+
if (__kmp_shm_available) {
6755+
int fd1 = -1;
6756+
shm_name = __kmp_str_format("/%s", name);
6757+
int shm_preexist = 0;
6758+
fd1 = shm_open(shm_name, O_CREAT | O_EXCL | O_RDWR, 0666);
6759+
if ((fd1 == -1) && (errno == EEXIST)) {
6760+
// file didn't open because it already exists.
6761+
// try opening existing file
6762+
fd1 = shm_open(shm_name, O_RDWR, 0666);
6763+
if (fd1 == -1) { // file didn't open
6764+
KMP_WARNING(FunctionError, "Can't open SHM");
6765+
__kmp_shm_available = false;
6766+
} else { // able to open existing file
6767+
shm_preexist = 1;
6768+
}
6769+
}
6770+
if (__kmp_shm_available && shm_preexist == 0) { // SHM created, set size
6771+
if (ftruncate(fd1, SHM_SIZE) == -1) { // error occured setting size;
6772+
KMP_WARNING(FunctionError, "Can't set size of SHM");
6773+
__kmp_shm_available = false;
6774+
}
6775+
}
6776+
if (__kmp_shm_available) { // SHM exists, now map it
6777+
data1 = (char *)mmap(0, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
6778+
fd1, 0);
6779+
if (data1 == MAP_FAILED) { // failed to map shared memory
6780+
KMP_WARNING(FunctionError, "Can't map SHM");
6781+
__kmp_shm_available = false;
6782+
}
6783+
}
6784+
if (__kmp_shm_available) { // SHM mapped
6785+
if (shm_preexist == 0) { // set data to SHM, set value
6786+
KMP_STRCPY_S(data1, SHM_SIZE, __kmp_registration_str);
6787+
}
6788+
// Read value from either what we just wrote or existing file.
6789+
value = __kmp_str_format("%s", data1); // read value from SHM
6790+
munmap(data1, SHM_SIZE);
67646791
}
6765-
} else if (fd1 == -1) {
6766-
// SHM didn't open; it was due to error other than already exists. Try to
6767-
// create a temp file under /tmp.
6792+
if (fd1 != -1)
6793+
close(fd1);
6794+
}
6795+
if (!__kmp_shm_available)
6796+
__kmp_tmp_available = __kmp_detect_tmp();
6797+
if (!__kmp_shm_available && __kmp_tmp_available) {
6798+
// SHM failed to work due to an error other than that the file already
6799+
// exists. Try to create a temp file under /tmp.
6800+
// If /tmp isn't accessible, fall back to using environment variable.
67686801
// TODO: /tmp might not always be the temporary directory. For now we will
6769-
// not consider TMPDIR. If /tmp is not accessible, we simply error out.
6770-
char *temp_file_name = __kmp_str_format("/tmp/%sXXXXXX", name);
6771-
fd1 = mkstemp(temp_file_name);
6772-
if (fd1 == -1) {
6773-
// error out here.
6774-
__kmp_fatal(KMP_MSG(FunctionError, "Can't open TEMP"), KMP_ERR(errno),
6775-
__kmp_msg_null);
6802+
// not consider TMPDIR.
6803+
int fd1 = -1;
6804+
temp_reg_status_file_name = __kmp_str_format("/tmp/%s", name);
6805+
int tmp_preexist = 0;
6806+
fd1 = open(temp_reg_status_file_name, O_CREAT | O_EXCL | O_RDWR, 0666);
6807+
if ((fd1 == -1) && (errno == EEXIST)) {
6808+
// file didn't open because it already exists.
6809+
// try opening existing file
6810+
fd1 = open(temp_reg_status_file_name, O_RDWR, 0666);
6811+
if (fd1 == -1) { // file didn't open if (fd1 == -1) {
6812+
KMP_WARNING(FunctionError, "Can't open TEMP");
6813+
__kmp_tmp_available = false;
6814+
} else {
6815+
tmp_preexist = 1;
6816+
}
67766817
}
6777-
temp_reg_status_file_name = temp_file_name;
6778-
}
6779-
if (shm_preexist == 0) {
6780-
// we created SHM now set size
6781-
if (ftruncate(fd1, SHM_SIZE) == -1) {
6782-
// error occured setting size;
6783-
__kmp_fatal(KMP_MSG(FunctionError, "Can't set size of SHM"),
6784-
KMP_ERR(errno), __kmp_msg_null);
6818+
if (__kmp_tmp_available && tmp_preexist == 0) {
6819+
// we created /tmp file now set size
6820+
if (ftruncate(fd1, SHM_SIZE) == -1) { // error occured setting size;
6821+
KMP_WARNING(FunctionError, "Can't set size of /tmp file");
6822+
__kmp_tmp_available = false;
6823+
}
67856824
}
6825+
if (__kmp_tmp_available) {
6826+
data1 = (char *)mmap(0, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
6827+
fd1, 0);
6828+
if (data1 == MAP_FAILED) { // failed to map /tmp
6829+
KMP_WARNING(FunctionError, "Can't map /tmp");
6830+
__kmp_tmp_available = false;
6831+
}
6832+
}
6833+
if (__kmp_tmp_available) {
6834+
if (tmp_preexist == 0) { // set data to TMP, set value
6835+
KMP_STRCPY_S(data1, SHM_SIZE, __kmp_registration_str);
6836+
}
6837+
// Read value from either what we just wrote or existing file.
6838+
value = __kmp_str_format("%s", data1); // read value from SHM
6839+
munmap(data1, SHM_SIZE);
6840+
}
6841+
if (fd1 != -1)
6842+
close(fd1);
67866843
}
6787-
data1 =
6788-
(char *)mmap(0, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd1, 0);
6789-
if (data1 == MAP_FAILED) {
6790-
// failed to map shared memory
6791-
__kmp_fatal(KMP_MSG(FunctionError, "Can't map SHM"), KMP_ERR(errno),
6792-
__kmp_msg_null);
6793-
}
6794-
if (shm_preexist == 0) { // set data to SHM, set value
6795-
KMP_STRCPY_S(data1, SHM_SIZE, __kmp_registration_str);
6844+
if (!__kmp_shm_available && !__kmp_tmp_available) {
6845+
// no /dev/shm and no /tmp -- fall back to environment variable
6846+
// Set environment variable, but do not overwrite if it exists.
6847+
__kmp_env_set(name, __kmp_registration_str, 0);
6848+
// read value to see if it got set
6849+
value = __kmp_env_get(name);
67966850
}
6797-
// Read value from either what we just wrote or existing file.
6798-
value = __kmp_str_format("%s", data1); // read value from SHM
6799-
munmap(data1, SHM_SIZE);
6800-
close(fd1);
68016851
#else // Windows and unix with static library
6802-
// Set environment variable, but do not overwrite if it is exist.
6852+
// Set environment variable, but do not overwrite if it exists.
68036853
__kmp_env_set(name, __kmp_registration_str, 0);
68046854
// read value to see if it got set
68056855
value = __kmp_env_get(name);
@@ -6859,8 +6909,14 @@ void __kmp_register_library_startup(void) {
68596909
case 2: { // Neighbor is dead.
68606910

68616911
#if defined(KMP_USE_SHM)
6862-
// close shared memory.
6863-
shm_unlink(shm_name); // this removes file in /dev/shm
6912+
if (__kmp_shm_available) { // close shared memory.
6913+
shm_unlink(shm_name); // this removes file in /dev/shm
6914+
} else if (__kmp_tmp_available) {
6915+
unlink(temp_reg_status_file_name); // this removes the temp file
6916+
} else {
6917+
// Clear the variable and try to register library again.
6918+
__kmp_env_unset(name);
6919+
}
68646920
#else
68656921
// Clear the variable and try to register library again.
68666922
__kmp_env_unset(name);
@@ -6873,7 +6929,8 @@ void __kmp_register_library_startup(void) {
68736929
}
68746930
KMP_INTERNAL_FREE((void *)value);
68756931
#if defined(KMP_USE_SHM)
6876-
KMP_INTERNAL_FREE((void *)shm_name);
6932+
if (shm_name)
6933+
KMP_INTERNAL_FREE((void *)shm_name);
68776934
#endif
68786935
} // while
68796936
KMP_INTERNAL_FREE((void *)name);
@@ -6886,25 +6943,32 @@ void __kmp_unregister_library(void) {
68866943
char *value = NULL;
68876944

68886945
#if defined(KMP_USE_SHM)
6889-
bool use_shm = true;
6890-
char *shm_name = __kmp_str_format("/%s", name);
6891-
int fd1 = shm_open(shm_name, O_RDONLY, 0666);
6892-
if (fd1 == -1) {
6893-
// File did not open. Try the temporary file.
6894-
use_shm = false;
6895-
KMP_DEBUG_ASSERT(temp_reg_status_file_name);
6946+
char *shm_name = nullptr;
6947+
int fd1;
6948+
if (__kmp_shm_available) {
6949+
shm_name = __kmp_str_format("/%s", name);
6950+
fd1 = shm_open(shm_name, O_RDONLY, 0666);
6951+
if (fd1 != -1) { // File opened successfully
6952+
char *data1 = (char *)mmap(0, SHM_SIZE, PROT_READ, MAP_SHARED, fd1, 0);
6953+
if (data1 != MAP_FAILED) {
6954+
value = __kmp_str_format("%s", data1); // read value from SHM
6955+
munmap(data1, SHM_SIZE);
6956+
}
6957+
close(fd1);
6958+
}
6959+
} else if (__kmp_tmp_available) { // try /tmp
68966960
fd1 = open(temp_reg_status_file_name, O_RDONLY);
6897-
if (fd1 == -1) {
6898-
// give it up now.
6899-
return;
6961+
if (fd1 != -1) { // File opened successfully
6962+
char *data1 = (char *)mmap(0, SHM_SIZE, PROT_READ, MAP_SHARED, fd1, 0);
6963+
if (data1 != MAP_FAILED) {
6964+
value = __kmp_str_format("%s", data1); // read value from /tmp
6965+
munmap(data1, SHM_SIZE);
6966+
}
6967+
close(fd1);
69006968
}
6969+
} else { // fall back to envirable
6970+
value = __kmp_env_get(name);
69016971
}
6902-
char *data1 = (char *)mmap(0, SHM_SIZE, PROT_READ, MAP_SHARED, fd1, 0);
6903-
if (data1 != MAP_FAILED) {
6904-
value = __kmp_str_format("%s", data1); // read value from SHM
6905-
munmap(data1, SHM_SIZE);
6906-
}
6907-
close(fd1);
69086972
#else
69096973
value = __kmp_env_get(name);
69106974
#endif
@@ -6914,23 +6978,23 @@ void __kmp_unregister_library(void) {
69146978
if (value != NULL && strcmp(value, __kmp_registration_str) == 0) {
69156979
// Ok, this is our variable. Delete it.
69166980
#if defined(KMP_USE_SHM)
6917-
if (use_shm) {
6981+
if (__kmp_shm_available) {
69186982
shm_unlink(shm_name); // this removes file in /dev/shm
6919-
} else {
6920-
KMP_DEBUG_ASSERT(temp_reg_status_file_name);
6983+
} else if (__kmp_tmp_available) {
69216984
unlink(temp_reg_status_file_name); // this removes the temp file
6985+
} else {
6986+
__kmp_env_unset(name);
69226987
}
69236988
#else
69246989
__kmp_env_unset(name);
69256990
#endif
69266991
}
69276992

69286993
#if defined(KMP_USE_SHM)
6929-
KMP_INTERNAL_FREE(shm_name);
6930-
if (!use_shm) {
6931-
KMP_DEBUG_ASSERT(temp_reg_status_file_name);
6994+
if (shm_name)
6995+
KMP_INTERNAL_FREE(shm_name);
6996+
if (temp_reg_status_file_name)
69326997
KMP_INTERNAL_FREE(temp_reg_status_file_name);
6933-
}
69346998
#endif
69356999

69367000
KMP_INTERNAL_FREE(__kmp_registration_str);

openmp/runtime/src/z_Linux_util.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2744,4 +2744,28 @@ void __kmp_hidden_helper_threads_deinitz_release() {
27442744
}
27452745
#endif // KMP_OS_LINUX
27462746

2747+
bool __kmp_detect_shm() {
2748+
DIR *dir = opendir("/dev/shm");
2749+
if (dir) { // /dev/shm exists
2750+
closedir(dir);
2751+
return true;
2752+
} else if (ENOENT == errno) { // /dev/shm does not exist
2753+
return false;
2754+
} else { // opendir() failed
2755+
return false;
2756+
}
2757+
}
2758+
2759+
bool __kmp_detect_tmp() {
2760+
DIR *dir = opendir("/tmp");
2761+
if (dir) { // /tmp exists
2762+
closedir(dir);
2763+
return true;
2764+
} else if (ENOENT == errno) { // /tmp does not exist
2765+
return false;
2766+
} else { // opendir() failed
2767+
return false;
2768+
}
2769+
}
2770+
27472771
// end of file //

0 commit comments

Comments
 (0)