[PATCH] D20913: [asan] add primitives that allow coroutine implementations
Dmitry Vyukov via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 13 02:00:30 PDT 2016
dvyukov added a comment.
> Another downside is that getting the current thread's stack bounds is done through a non-portable pthread API, but it does simplify asan code.
I only see the APIs in test code. Is it correct?
Tests are OK. swapcontext is also non-portable.
================
Comment at: lib/asan/asan_thread.cc:133
@@ +132,3 @@
+ if (!stack_switching_)
+ Report("WARNING: finishing a fiber enter that has not started\n");
+ // order is important so that the range [bottom, top] is empty until we are
----------------
If you want to tolerate some user errors here, then I think it's better to return here. next_stack_top/bottom are most likely 0, so we will end up with no stack at all otherwise.
================
Comment at: lib/asan/asan_thread.cc:147
@@ +146,3 @@
+ if (!stack_switching_) {
+ if (next_stack_top_ && next_stack_bottom_)
+ return StackBounds{next_stack_bottom_, next_stack_top_}; // NOLINT
----------------
Why?
If I am reading core correctly, this must never happen.
> I made my implementation more signal-proof by using volatile. I saw later that in some other parts of the code, you prefer using atomic access, I can change the volatiles to that if needed.
Yes, please.
Current ordering of memory accesses if very tricky, esp in FinishSwitchFiber and I see that that is actually important for GetStackBounds correctness.
I think it is enough to make only stack_switching_ atomic:
atomic<int> stack_switching_;
void AsanThread::StartSwitchFiber(uptr bottom, uptr size) {
next_stack_bottom_ = bottom;
next_stack_top_ = bottom + size;
atomic_store(&stack_switching_, 1, memory_order_release);
}
void AsanThread::FinishSwitchFiber() {
stack_bottom_ = next_stack_bottom_;
stack_top_ = next_stack_top_;
atomic_store(&stack_switching_, 0, memory_order_release);
next_stack_top_ = 0;
next_stack_bottom_ = 0;
}
inline AsanThread::StackBounds AsanThread::GetStackBounds() const {
if (!atomic_load(&stack_switching_, memory_order_acquire))
return StackBounds{stack_bottom_, stack_top_}; // NOLINT
char local;
const uptr cur_stack = (uptr)&local;
// Note: need to check next stack first, because FinishSwitchFiber
// may be in process of overwriting stack_top_/bottom_. But in such case
// we are already on the next stack.
if (cur_stack >= next_stack_bottom_ && cur_stack < next_stack_top_)
return StackBounds{next_stack_bottom_, next_stack_top_}; // NOLINT
return StackBounds{stack_bottom_, stack_top_}; // NOLINT
}
================
Comment at: test/asan/TestCases/Linux/swapcontext_annotation.cc:5
@@ +4,3 @@
+// function
+// RUN: %clangxx_asan -lpthread -O0 %s -o %t
+// RUN: %run %t x 2>&1 | FileCheck %s
----------------
I would expect that we do all that -O0/-O1/-O2 automatically on a higher level. At least we used to as far as I remember. Now all that cmake/lit in incomprehensible, so I am not sure... But I don't see any -O flags in other asan tests.
Does anybody know is we run asan lit tests with different optimization levels?
================
Comment at: test/asan/TestCases/Linux/swapcontext_annotation.cc:67
@@ +66,3 @@
+ perror("swapcontext");
+ _exit(0);
+ }
----------------
s/0/1/
otherwise test can silently break and continue passing on bots
================
Comment at: test/asan/TestCases/Linux/swapcontext_annotation.cc:89
@@ +88,3 @@
+ perror("swapcontext");
+ _exit(0);
+ }
----------------
s/0/1/
================
Comment at: test/asan/TestCases/Linux/swapcontext_annotation.cc:101
@@ +100,3 @@
+ perror("swapcontext");
+ _exit(0);
+ }
----------------
s/0/1/
================
Comment at: test/asan/TestCases/Linux/swapcontext_annotation.cc:136
@@ +135,3 @@
+void handler(int sig)
+{
+ ThrowAndCatch();
----------------
please reformat tests with clang-format
{ should be on the previous line
================
Comment at: test/asan/TestCases/Linux/swapcontext_annotation.cc:155
@@ +154,3 @@
+
+ if (argv[1][0] == 's')
+ {
----------------
Is it useful to run the test without the signal ('x' above)?
I would expect that the signal variant is a strict superset of no-signal. I can't imagine how signals can prevent some failure from happening.
If you agree, then remove the 'x' runs.
================
Comment at: test/asan/TestCases/Linux/swapcontext_annotation.cc:175
@@ +174,3 @@
+
+ char *heap = new char[kStackSize + 1];
+ next_child_stack = new char[kStackSize + 1];
----------------
Run all the following 10000 times (or whatever makes it run for 100ms or so). That will allow to stress interaction with signals better.
http://reviews.llvm.org/D20913
More information about the llvm-commits
mailing list