Skip to content

Commit 1f061b5

Browse files
committed
fix: prevent deadlocks when instrumenting with clippy-tracing
Two deadlock sources exist when clippy-tracing instruments the codebase: 1. Logger::update() called open_file_nonblock() while holding the LOGGER mutex. When instrumented, that function calls log::trace!() which re-enters Logger::log() and attempts to acquire the same non-reentrant mutex, causing a deadlock on startup. 2. Signal handlers (extern C fns) were instrumented by clippy-tracing, adding mutex acquisitions in async-signal-unsafe contexts. When a signal interrupted a thread already holding the LOGGER mutex, the handler would deadlock trying to acquire it again. Fix (1) by moving the open_file_nonblock() call before the mutex is acquired in Logger::update(). Fix (2) by teaching clippy-tracing to skip functions with an explicit ABI (e.g. extern C), since these are typically signal handlers or FFI callbacks that must not acquire locks. Closes #5807 Signed-off-by: snigenigmatic <kaustubhc.1105@gmail.com>
1 parent fc4cb9c commit 1f061b5

2 files changed

Lines changed: 4 additions & 9 deletions

File tree

src/clippy-tracing/src/main.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,7 @@ macro_rules! create_check_visitor_function {
128128
($func_name:ident, $item:ident) => {
129129
fn $func_name(&mut self, i: &syn::$item) {
130130
let attr = check_attributes(&i.attrs);
131-
if !attr.instrumented
132-
&& !attr.test
133-
&& i.sig.constness.is_none()
134-
&& i.sig.abi.is_none()
131+
if !attr.instrumented && !attr.test && i.sig.constness.is_none() && i.sig.abi.is_none()
135132
{
136133
self.0 = Some(i.span());
137134
} else {
@@ -166,10 +163,7 @@ macro_rules! create_fix_visitor_function {
166163
fn $func_name(&mut self, i: &syn::$item) {
167164
let attr = check_attributes(&i.attrs);
168165

169-
if !attr.instrumented
170-
&& !attr.test
171-
&& i.sig.constness.is_none()
172-
&& i.sig.abi.is_none()
166+
if !attr.instrumented && !attr.test && i.sig.constness.is_none() && i.sig.abi.is_none()
173167
{
174168
let line = i.span().start().line;
175169

src/clippy-tracing/tests/integration_tests.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,8 @@ fn check_skips_extern_c_fn() {
431431

432432
#[test]
433433
fn fix_skips_extern_c_fn_in_impl() {
434-
const GIVEN: &str = "struct S;\nimpl S {\n extern \"C\" fn callback() {}\n fn normal() {}\n}";
434+
const GIVEN: &str =
435+
"struct S;\nimpl S {\n extern \"C\" fn callback() {}\n fn normal() {}\n}";
435436
const EXPECTED: &str = "struct S;\nimpl S {\n extern \"C\" fn callback() {}\n #[log_instrument::instrument]\n fn normal() {}\n}";
436437
fix(GIVEN, EXPECTED, None);
437438
}

0 commit comments

Comments
 (0)