[PATCH] D46517: [sanitizer] Don't miss threads by ThreadSuspender
Vitaly Buka via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Mon May 7 14:01:35 PDT 2018
vitalybuka added a comment.
here I explain what I see WITHOUT this patch:
I have small program which creates 30 threads, which exit almost immediately. And another thread which runs __lsan_do_recoverable_leak_check().
Here the last successful __lsan_do_recoverable_leak_check
SuspendAllThreads
ThreadLister::ListThreads
internal_getdents: 840
/proc/6563/task/6563
/proc/6563/task/6564
/proc/6563/task/6565
/proc/6563/task/6566
/proc/6563/task/6929
/proc/6563/task/6930
/proc/6563/task/6931
/proc/6563/task/6932
/proc/6563/task/6933
/proc/6563/task/6934
/proc/6563/task/6935
/proc/6563/task/6936
/proc/6563/task/6939
/proc/6563/task/6940
/proc/6563/task/6941
/proc/6563/task/6942
/proc/6563/task/6943
/proc/6563/task/6944
/proc/6563/task/6945
/proc/6563/task/6946
/proc/6563/task/6949
/proc/6563/task/6950
/proc/6563/task/6951
/proc/6563/task/6952
/proc/6563/task/6955
/proc/6563/task/6956
/proc/6563/task/6957
/proc/6563/task/6958
/proc/6563/task/6959
/proc/6563/task/6960
/proc/6563/task/6961
/proc/6563/task/6966
/proc/6563/task/6968
internal_getdents: 0
ThreadLister::ListThreads
internal_getdents: 840
/proc/6563/task/6563
/proc/6563/task/6564
/proc/6563/task/6565
/proc/6563/task/6566
/proc/6563/task/6929
/proc/6563/task/6930
/proc/6563/task/6931
/proc/6563/task/6932
/proc/6563/task/6933
/proc/6563/task/6934
/proc/6563/task/6935
/proc/6563/task/6936
/proc/6563/task/6939
/proc/6563/task/6940
/proc/6563/task/6941
/proc/6563/task/6942
/proc/6563/task/6943
/proc/6563/task/6944
/proc/6563/task/6945
/proc/6563/task/6946
/proc/6563/task/6949
/proc/6563/task/6950
/proc/6563/task/6951
/proc/6563/task/6952
/proc/6563/task/6955
/proc/6563/task/6956
/proc/6563/task/6957
/proc/6563/task/6958
/proc/6563/task/6959
/proc/6563/task/6960
/proc/6563/task/6961
/proc/6563/task/6966
/proc/6563/task/6968
internal_getdents: 0
Leak check iterated list twice with same list of thread and suspended following:
Suspended
suspended: 6563
suspended: 6564
suspended: 6565
suspended: 6566
suspended: 6929
suspended: 6930
suspended: 6931
suspended: 6932
suspended: 6933
suspended: 6934
suspended: 6935
suspended: 6936
suspended: 6939
suspended: 6940
suspended: 6941
suspended: 6942
suspended: 6943
suspended: 6944
suspended: 6945
suspended: 6946
suspended: 6949
suspended: 6950
suspended: 6951
suspended: 6952
suspended: 6955
suspended: 6956
suspended: 6957
suspended: 6958
suspended: 6959
suspended: 6960
suspended: 6961
suspended: 6966
suspended: 6968
Note threads 6958 and 6968.
The next call to __lsan_do_recoverable_leak_check()
SuspendAllThreads
ThreadLister::ListThreads
internal_getdents: 240
/proc/6563/task/6563
/proc/6563/task/6564
/proc/6563/task/6565
/proc/6563/task/6566
/proc/6563/task/6930
/proc/6563/task/6942
/proc/6563/task/6944
/proc/6563/task/6950
internal_getdents: 0
Some threads are gone including 6958 and 6968.
The second internal_getdents returned 0 so it looks like a complete list.
Do one more iterations:
ThreadLister::ListThreads
internal_getdents: 168
/proc/6563/task/6563
/proc/6563/task/6564
/proc/6563/task/6565
/proc/6563/task/6566
/proc/6563/task/6958
internal_getdents: 0
Suspended
suspended: 6563
suspended: 6564
suspended: 6565
suspended: 6566
Thread 6958 is exiting so we failed to suspend it and we return from SuspendAllThreads.
However if we call ThreadLister one more time (just for debugging, without actually suspending):
ThreadLister::ListThreads
internal_getdents: 168
/proc/6563/task/6563
/proc/6563/task/6564
/proc/6563/task/6565
/proc/6563/task/6566
/proc/6563/task/6968
internal_getdents: 0
6968 is back and we didn't suspend it.
Then we proceed leak checking and get:
==6563==ERROR: LeakSanitizer: detected memory leaks
Objects leaked above:
0x613000072500 (352 bytes)
If we ignore the leak and continue, next call to __lsan_do_recoverable_leak_check will see and suspend 6968 thread again.
SuspendAllThreads
ThreadLister::ListThreads
internal_getdents: 168
/proc/6563/task/6563
/proc/6563/task/6564
/proc/6563/task/6565
/proc/6563/task/6566
/proc/6563/task/6968
internal_getdents: 0
ThreadLister::ListThreads
internal_getdents: 168
/proc/6563/task/6563
/proc/6563/task/6564
/proc/6563/task/6565
/proc/6563/task/6566
/proc/6563/task/6968
internal_getdents: 0
Suspended
suspended: 6563
suspended: 6564
suspended: 6565
suspended: 6566
suspended: 6968
So obviously increasing iteration highly reduce probability of missing threads but not guaranty correctness.
Reason is probably this place https://github.com/torvalds/linux/blob/master/fs/proc/base.c#L3601
After exiting here on dying thread, next call to proc_task_readdir fail to restore position, and we can't see this.
Repository:
rL LLVM
https://reviews.llvm.org/D46517
More information about the llvm-commits
mailing list