diff --git a/openmp/runtime/src/kmp_lock.cpp b/openmp/runtime/src/kmp_lock.cpp index 0ad14f862bcb9..11fa233c4bd27 100644 --- a/openmp/runtime/src/kmp_lock.cpp +++ b/openmp/runtime/src/kmp_lock.cpp @@ -3242,6 +3242,8 @@ static void __kmp_destroy_indirect_lock(kmp_dyna_lock_t *lock) { kmp_uint32 gtid = __kmp_entry_gtid(); kmp_indirect_lock_t *l = __kmp_lookup_indirect_lock((void **)lock, "omp_destroy_lock"); + if (l == nullptr) + return; // avoid segv if lock already destroyed KMP_I_LOCK_FUNC(l, destroy)(l->lock); kmp_indirect_locktag_t tag = l->type; diff --git a/openmp/runtime/test/ompt/misc/lock_double_destroy.cpp b/openmp/runtime/test/ompt/misc/lock_double_destroy.cpp new file mode 100644 index 0000000000000..bbdf348e97e7c --- /dev/null +++ b/openmp/runtime/test/ompt/misc/lock_double_destroy.cpp @@ -0,0 +1,40 @@ +// RUN: %libomp-cxx-compile-and-run | FileCheck %s +// REQUIRES: ompt +#include "callback.h" +#include "omp_testsuite.h" + +// tests that the destructor doesn't segv even though +// ompt_finalize_tool() destroys the lock +struct myLock { + omp_lock_t lock; + myLock() { omp_init_lock(&lock); } + ~myLock() { omp_destroy_lock(&lock); } +}; + +myLock lock; + +int main() { + go_parallel_nthreads(2); + + printf("Before ompt_finalize_tool\n"); + ompt_finalize_tool(); + printf("After ompt_finalize_tool\n"); + + return get_exit_value(); +} + +// CHECK: 0: NULL_POINTER=[[NULL:.*$]] +// CHECK: {{^}}[[THREAD_ID:[0-9]+]]: ompt_event_thread_begin: +// CHECK-SAME: thread_type=ompt_thread_initial=1 + +// CHECK: {{^}}[[THREAD_ID]]: ompt_event_init_lock + +// CHECK: {{^}}[[THREAD_ID]]: ompt_event_parallel_begin +// CHECK: {{^}}[[THREAD_ID]]: ompt_event_parallel_end + +// CHECK: {{^}}Before ompt_finalize_tool + +// CHECK: {{^}}[[THREAD_ID]]: ompt_event_thread_end: thread_id=[[THREAD_ID]] +// CHECK: 0: ompt_event_runtime_shutdown + +// CHECK: {{^}}After ompt_finalize_tool