parking_lot: Possible bug - UB

Based on recent reddit post there may be a bug in CondVar::wait_until_internal(). Sadly the OP didn’t provide more information and I didn’t find anything wrong in the code. I didn’t check too deeply so it’d be nice if someone else tried to check too if I missed something.

About this issue

  • Original URL
  • State: open
  • Created 3 years ago
  • Comments: 18 (7 by maintainers)

Most upvoted comments

OP here! I’ve reproduced this bug in debug mode with the following stacktrace. As suspected it is happening in grow_hashtable

#0  0x00007f1eca5f9a9b in __memmove_avx_unaligned_erms () at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:309
#1  0x000055a0b5cc4ab9 in core::intrinsics::copy_nonoverlapping (src=0x7f1d6affb508, dst=0x7f1ec5cf4120 <inflate_fast+64>, count=1) at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/core/src/intrinsics.rs:1860
#2  0x000055a0b5cc6c73 in core::ptr::swap_nonoverlapping_one (x=0x7f1ec5cf4120 <inflate_fast+64>, y=0x7f1d6affb508) at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/core/src/ptr/mod.rs:455
#3  0x000055a0b5cc4e24 in core::mem::swap (x=0x7f1ec5cf4120 <inflate_fast+64>, y=0x7f1d6affb508) at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/core/src/mem/mod.rs:688
#4  0x000055a0b5cc4f9c in core::mem::replace (dest=0x7f1ec5cf4120 <inflate_fast+64>, src=0x0) at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/core/src/mem/mod.rs:815
#5  0x000055a0b5cbf495 in core::cell::Cell<T>::replace (self=0x7f1ec5cf4120 <inflate_fast+64>, val=0x0) at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/core/src/cell.rs:393
#6  0x000055a0b5cbf374 in core::cell::Cell<T>::set (self=0x7f1ec5cf4120 <inflate_fast+64>, val=0x0) at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/core/src/cell.rs:344
#7  0x000055a0b5cbe8f5 in parking_lot_core::parking_lot::rehash_bucket_into (bucket=0x7f1eac000d80, table=0x7f1d77c578f0) at /home/opencpu/.cargo/registry/src/github.com-1ecc6299db9ec823/parking_lot_core-0.8.2/src/parking_lot.rs:314
#8  0x000055a0b5cbe55d in parking_lot_core::parking_lot::grow_hashtable (num_threads=11) at /home/opencpu/.cargo/registry/src/github.com-1ecc6299db9ec823/parking_lot_core-0.8.2/src/parking_lot.rs:277
#9  0x000055a0b5cbdfa2 in parking_lot_core::parking_lot::ThreadData::new () at /home/opencpu/.cargo/registry/src/github.com-1ecc6299db9ec823/parking_lot_core-0.8.2/src/parking_lot.rs:156
#10 0x000055a0b5cbea4e in parking_lot_core::parking_lot::with_thread_data::THREAD_DATA::__init () at /home/opencpu/.cargo/registry/src/github.com-1ecc6299db9ec823/parking_lot_core-0.8.2/src/parking_lot.rs:178
#11 0x000055a0b5cc59e0 in core::ops::function::FnOnce::call_once () at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/core/src/ops/function.rs:227
#12 0x000055a0b5cbfa0a in std::thread::local::lazy::LazyKeyInner<T>::initialize (self=0x7f1d6affd118, init=0x7f1eca4ff968 <_int_malloc+1304>) at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/std/src/thread/local.rs:304
#13 0x000055a0b5cbf766 in std::thread::local::fast::Key<T>::try_initialize (self=0x7f1d6affd118, init=0x0) at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/std/src/thread/local.rs:473
#14 0x000055a0b5cbf8ab in std::thread::local::fast::Key<T>::get (self=0x7f1d6affd118, init=0x7f1d6affd540) at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/std/src/thread/local.rs:456
#15 0x000055a0b5cbea7d in parking_lot_core::parking_lot::with_thread_data::THREAD_DATA::__getit () at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/std/src/thread/local.rs:183
#16 0x000055a0b5cbd53b in std::thread::local::LocalKey<T>::try_with (self=0x55a0b6572690, f=...) at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/std/src/thread/local.rs:271
#17 0x000055a0b5cbbfb6 in parking_lot_core::parking_lot::with_thread_data (f=...) at /home/opencpu/.cargo/registry/src/github.com-1ecc6299db9ec823/parking_lot_core-0.8.2/src/parking_lot.rs:179
#18 0x000055a0b5cbbfb6 in parking_lot_core::parking_lot::park (key=94149138538176, validate=..., before_sleep=..., timed_out=..., park_token=..., timeout=Python Exception <class 'gdb.MemoryError'> Cannot access memory at address 0x0:
#19 0x000055a0b5cb9303 in parking_lot::raw_mutex::RawMutex::lock_slow (self=0x55a0cdf55ec0, timeout=...)
    at /home/opencpu/.cargo/registry/src/github.com-1ecc6299db9ec823/parking_lot-0.11.1/src/raw_mutex.rs:262
#20 0x000055a0b5bda53b in <parking_lot::raw_mutex::RawMutex as lock_api::mutex::RawMutex>::lock (self=0x55a0cdf55ec0) at /home/opencpu/.cargo/registry/src/github.com-1ecc6299db9ec823/parking_lot-0.11.1/src/raw_mutex.rs:72
#21 0x000055a0b5bd2d39 in lock_api::mutex::Mutex<R,T>::lock (self=0x55a0cdf55ec0) at /home/opencpu/.cargo/registry/src/github.com-1ecc6299db9ec823/lock_api-0.4.2/src/mutex.rs:207
#22 0x000055a0b5bf1d5f in tokio::loom::std::parking_lot::Mutex<T>::lock (self=0x55a0cdf55ec0) at /home/opencpu/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.0.1/src/loom/std/parking_lot.rs:38
#23 0x000055a0b5c4bafd in tokio::runtime::blocking::pool::Inner::run (self=0x55a0cdf55ec0, worker_thread_id=1) at /home/opencpu/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.0.1/src/runtime/blocking/pool.rs:270
#24 0x000055a0b5c4b96e in tokio::runtime::blocking::pool::Spawner::spawn_thread::{{closure}} () at /home/opencpu/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.0.1/src/runtime/blocking/pool.rs:257
#25 0x000055a0b5bce7d3 in std::sys_common::backtrace::__rust_begin_short_backtrace (f=...) at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/std/src/sys_common/backtrace.rs:125
#26 0x000055a0b5bfce23 in std::thread::Builder::spawn_unchecked::{{closure}}::{{closure}} () at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/std/src/thread/mod.rs:474
#27 0x000055a0b5bae223 in <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once (self=..., _args=()) at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/std/src/panic.rs:322
#28 0x000055a0b5c38ff2 in std::panicking::try::do_call (data=0x7f1d6affc448 "\001") at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/std/src/panicking.rs:381
#29 0x000055a0b5c4426d in __rust_try ()
#30 0x000055a0b5c38a54 in std::panicking::try (f=...) at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/std/src/panicking.rs:345
#31 0x000055a0b5bae723 in std::panic::catch_unwind (f=...) at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/std/src/panic.rs:396
#32 0x000055a0b5bfcbe4 in std::thread::Builder::spawn_unchecked::{{closure}} () at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/std/src/thread/mod.rs:473
#33 0x000055a0b5c25f6f in core::ops::function::FnOnce::call_once{{vtable-shim}} () at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/core/src/ops/function.rs:227
#34 0x000055a0b5cf410a in <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once () at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/alloc/src/boxed.rs:1307
#35 0x000055a0b5cf410a in <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once () at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/alloc/src/boxed.rs:1307
#36 0x000055a0b5cf410a in std::sys::unix::thread::Thread::new::thread_start () at library/std/src/sys/unix/thread.rs:71
#37 0x00007f1ecae056db in start_thread (arg=0x7f1d6affd700) at pthread_create.c:463
#38 0x00007f1eca58c71f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95

Can you tell me more about it? It seems very strange that another library could affect the internals of parking_lot.

I think there is a bug somewhere in parking_lot, but it is very difficult for me to debug this without having a way to reproduce the crash.

Try passing --target x86_64-unknown-linux-gnu or whatever your system is to cargo. This will prevent cargo from using RUSTFLAGS when building host dependencies like proc macros and build scripts.

Can you try compiling and running the program with RUSTFLAGS=-Zsanitizer=address?

current.next_in_queue ins not cleared (set to ptr::null()) here

Doesn’t look correct to me but maybe I’m missing something?

It it cleared here.

And rehash_bucket_into() doesn’t clear bucket.queue_head nor bucket_queue_tail which also seems wrong or at least dangerous.

That shouldn’t matter since we are publishing a newer hash table. lock_bucket will immediately abort and retry with the new hash table, and never read the invalid pointers.