Skip to content

Commit 01b4801

Browse files
committed
avoid deadlock if crashing inside profile_wr_lock
1 parent e3f3466 commit 01b4801

File tree

4 files changed

+55
-21
lines changed

4 files changed

+55
-21
lines changed

src/debuginfo.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,8 @@ struct unw_table_entry
147147
template <typename T>
148148
static void jl_profile_atomic(T f) JL_NOTSAFEPOINT
149149
{
150-
assert(0 == jl_lock_profile_rd_held());
151-
jl_lock_profile_wr();
150+
int havelock = jl_lock_profile_wr();
151+
assert(havelock);
152152
#ifndef _OS_WINDOWS_
153153
sigset_t sset;
154154
sigset_t oset;
@@ -159,7 +159,8 @@ static void jl_profile_atomic(T f) JL_NOTSAFEPOINT
159159
#ifndef _OS_WINDOWS_
160160
pthread_sigmask(SIG_SETMASK, &oset, NULL);
161161
#endif
162-
jl_unlock_profile_wr();
162+
if (havelock)
163+
jl_unlock_profile_wr();
163164
}
164165

165166

@@ -475,8 +476,8 @@ static int lookup_pointer(
475476

476477
// DWARFContext/DWARFUnit update some internal tables during these queries, so
477478
// a lock is needed.
478-
assert(0 == jl_lock_profile_rd_held());
479-
jl_lock_profile_wr();
479+
if (!jl_lock_profile_wr())
480+
return lookup_pointer(object::SectionRef(), NULL, frames, pointer, slide, demangle, noInline);
480481
auto inlineInfo = context->getInliningInfoForAddress(makeAddress(Section, pointer + slide), infoSpec);
481482
jl_unlock_profile_wr();
482483

@@ -501,7 +502,8 @@ static int lookup_pointer(
501502
info = inlineInfo.getFrame(i);
502503
}
503504
else {
504-
jl_lock_profile_wr();
505+
int havelock = jl_lock_profile_wr();
506+
assert(havelock); (void)havelock;
505507
info = context->getLineInfoForAddress(makeAddress(Section, pointer + slide), infoSpec);
506508
jl_unlock_profile_wr();
507509
}
@@ -1209,8 +1211,8 @@ int jl_DI_for_fptr(uint64_t fptr, uint64_t *symsize, int64_t *slide,
12091211
object::SectionRef *Section, llvm::DIContext **context) JL_NOTSAFEPOINT
12101212
{
12111213
int found = 0;
1212-
assert(0 == jl_lock_profile_rd_held());
1213-
jl_lock_profile_wr();
1214+
if (!jl_lock_profile_wr())
1215+
return 0;
12141216

12151217
if (symsize)
12161218
*symsize = 0;

src/julia_internal.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,9 @@ JL_DLLEXPORT double jl_get_profile_peek_duration(void);
210210
JL_DLLEXPORT void jl_set_profile_peek_duration(double);
211211

212212
JL_DLLEXPORT void jl_init_profile_lock(void);
213-
JL_DLLEXPORT uintptr_t jl_lock_profile_rd_held(void) JL_NOTSAFEPOINT;
214-
JL_DLLEXPORT void jl_lock_profile(void) JL_NOTSAFEPOINT JL_NOTSAFEPOINT_ENTER;
213+
JL_DLLEXPORT int jl_lock_profile(void) JL_NOTSAFEPOINT JL_NOTSAFEPOINT_ENTER;
215214
JL_DLLEXPORT void jl_unlock_profile(void) JL_NOTSAFEPOINT JL_NOTSAFEPOINT_LEAVE;
216-
JL_DLLEXPORT void jl_lock_profile_wr(void) JL_NOTSAFEPOINT JL_NOTSAFEPOINT_ENTER;
215+
JL_DLLEXPORT int jl_lock_profile_wr(void) JL_NOTSAFEPOINT JL_NOTSAFEPOINT_ENTER;
217216
JL_DLLEXPORT void jl_unlock_profile_wr(void) JL_NOTSAFEPOINT JL_NOTSAFEPOINT_LEAVE;
218217
void jl_with_stackwalk_lock(void (*f)(void*) JL_NOTSAFEPOINT, void *ctx) JL_NOTSAFEPOINT;
219218

src/signal-handling.c

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ void jl_init_profile_lock(void)
102102
#endif
103103
}
104104

105-
uintptr_t jl_lock_profile_rd_held(void)
105+
static uintptr_t jl_lock_profile_rd_held(void)
106106
{
107107
#ifndef _OS_WINDOWS_
108108
return (uintptr_t)pthread_getspecific(debuginfo_asyncsafe_held);
@@ -111,38 +111,69 @@ uintptr_t jl_lock_profile_rd_held(void)
111111
#endif
112112
}
113113

114-
void jl_lock_profile(void)
114+
int jl_lock_profile(void)
115115
{
116116
uintptr_t held = jl_lock_profile_rd_held();
117-
if (held++ == 0)
117+
if (held == -1)
118+
return 0;
119+
if (held == 0) {
120+
held = -1;
121+
#ifndef _OS_WINDOWS_
122+
pthread_setspecific(debuginfo_asyncsafe_held, (void*)held);
123+
#else
124+
TlsSetValue(debuginfo_asyncsafe_held, (void*)held);
125+
#endif
118126
uv_rwlock_rdlock(&debuginfo_asyncsafe);
127+
held = 0;
128+
}
129+
held++;
119130
#ifndef _OS_WINDOWS_
120131
pthread_setspecific(debuginfo_asyncsafe_held, (void*)held);
121132
#else
122133
TlsSetValue(debuginfo_asyncsafe_held, (void*)held);
123134
#endif
135+
return 1;
124136
}
125137

126138
JL_DLLEXPORT void jl_unlock_profile(void)
127139
{
128140
uintptr_t held = jl_lock_profile_rd_held();
129-
assert(held);
130-
if (--held == 0)
131-
uv_rwlock_rdunlock(&debuginfo_asyncsafe);
141+
assert(held && held != -1);
142+
held--;
132143
#ifndef _OS_WINDOWS_
133144
pthread_setspecific(debuginfo_asyncsafe_held, (void*)held);
134145
#else
135146
TlsSetValue(debuginfo_asyncsafe_held, (void*)held);
136147
#endif
148+
if (held == 0)
149+
uv_rwlock_rdunlock(&debuginfo_asyncsafe);
137150
}
138151

139-
void jl_lock_profile_wr(void)
152+
int jl_lock_profile_wr(void)
140153
{
154+
uintptr_t held = jl_lock_profile_rd_held();
155+
if (held)
156+
return 0;
157+
held = -1;
158+
#ifndef _OS_WINDOWS_
159+
pthread_setspecific(debuginfo_asyncsafe_held, (void*)held);
160+
#else
161+
TlsSetValue(debuginfo_asyncsafe_held, (void*)held);
162+
#endif
141163
uv_rwlock_wrlock(&debuginfo_asyncsafe);
164+
return 1;
142165
}
143166

144167
void jl_unlock_profile_wr(void)
145168
{
169+
uintptr_t held = jl_lock_profile_rd_held();
170+
assert(held == -1);
171+
held = 0;
172+
#ifndef _OS_WINDOWS_
173+
pthread_setspecific(debuginfo_asyncsafe_held, (void*)held);
174+
#else
175+
TlsSetValue(debuginfo_asyncsafe_held, (void*)held);
176+
#endif
146177
uv_rwlock_wrunlock(&debuginfo_asyncsafe);
147178
}
148179

src/threading.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -559,18 +559,20 @@ static void jl_delete_thread(void *value) JL_NOTSAFEPOINT_ENTER
559559
// this here by blocking. This also synchronizes our read of `current_task`
560560
// (which is the flag we currently use to check the liveness state of a thread).
561561
#ifdef _OS_WINDOWS_
562-
jl_lock_profile_wr();
562+
int havelock = jl_lock_profile_wr();
563+
assert(havelock); (void)havelock;
563564
#elif defined(JL_DISABLE_LIBUNWIND)
564565
// nothing
565566
#elif defined(__APPLE__)
566-
jl_lock_profile_wr();
567+
int havelock = jl_lock_profile_wr();
568+
assert(havelock); (void)havelock;
567569
#else
568570
pthread_mutex_lock(&in_signal_lock);
569571
#endif
570572
jl_atomic_store_relaxed(&ptls->current_task, NULL); // indicate dead
571573
// finally, release all of the locks we had grabbed
572574
#ifdef _OS_WINDOWS_
573-
jl_unlock_profile_wr();
575+
if (havelock) jl_unlock_profile_wr();
574576
#elif defined(JL_DISABLE_LIBUNWIND)
575577
// nothing
576578
#elif defined(__APPLE__)

0 commit comments

Comments
 (0)