Summary: The test (among other things) attempts to verify that detaching works while the inferior is running. However, this was racy since the inferior could end up stopping again before we got a chance to detach from it (the test could be made to fail reliably by inserting a sleep just after the last "continue" command). The reason for the stop was that we had a breakpoint set in a place that can be hit by multiple threads, and we stop because another thread hit a breakpoint. I fix this by moving the breakpoint to a place that is reachable from only one thread. I also make sure that the same thread cannot hit the breakpoint if we are exceptionaly slow by flipping a flag which makes the breakpoint unreachable (I cannot just disable or delete the breakpoint as the test makes it a point to try detaching while breakpoints are still set). Another source or racyness was that the test verified that the process resumes and stops after a "continue". However, if these two events happened too fast, the initial start event would be lost, and the test would end up confused. I have implemented this in a safer manner and made a utility function out of it, as I know of a couple of other tests which need the same functionality. Reviewers: zturner, clayborg Subscribers: lldb-commits Differential Revision: http://reviews.llvm.org/D12527 llvm-svn: 246623
51 lines
1.4 KiB
C++
51 lines
1.4 KiB
C++
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
|
|
#include <chrono>
|
|
#include <thread>
|
|
|
|
#if defined(__linux__)
|
|
#include <sys/prctl.h>
|
|
#endif
|
|
|
|
volatile bool debugger_flag = true; // The debugger will flip this to false
|
|
|
|
void *start(void *data)
|
|
{
|
|
int i;
|
|
size_t idx = (size_t)data;
|
|
for (i=0; i<30; i++)
|
|
{
|
|
if ( idx == 0 && debugger_flag)
|
|
std::this_thread::sleep_for(std::chrono::microseconds(1)); // Set breakpoint here
|
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char const *argv[])
|
|
{
|
|
#if defined(__linux__)
|
|
// Immediately enable any ptracer so that we can allow the stub attach
|
|
// operation to succeed. Some Linux kernels are locked down so that
|
|
// only an ancestor process can be a ptracer of a process. This disables that
|
|
// restriction. Without it, attach-related stub tests will fail.
|
|
#if defined(PR_SET_PTRACER) && defined(PR_SET_PTRACER_ANY)
|
|
// For now we execute on best effort basis. If this fails for
|
|
// some reason, so be it.
|
|
const int prctl_result = prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0);
|
|
static_cast<void> (prctl_result);
|
|
#endif
|
|
#endif
|
|
|
|
static const size_t nthreads = 16;
|
|
std::thread threads[nthreads];
|
|
size_t i;
|
|
|
|
for (i=0; i<nthreads; i++)
|
|
threads[i] = std::move(std::thread(start, (void*)i));
|
|
|
|
for (i=0; i<nthreads; i++)
|
|
threads[i].join();
|
|
}
|