[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