Reviewers: Søren Gjesse,

Description:
Fix issue 410: test-log/ProfLazyMode flakinness under Linux.

I found two causes of flakinness:
  - SIGPROF signal isn't delivered to a process;
  - Profiler thread (the one that retrieves tick events from
    the queue and writes to log) doesn't get a CPU;
Both are fixed.

The script from bug description with run count increased to 200 runs
without any test failures.

OS X and Windows are unaffected because they don't use signals
mechanism.

BUG=http://code.google.com/p/v8/issues/detail?id=410
TEST=see bug description

Please review this at http://codereview.chromium.org/159406

Affected files:
   M test/cctest/test-log.cc


Index: test/cctest/test-log.cc
diff --git a/test/cctest/test-log.cc b/test/cctest/test-log.cc
index  
f3f7efc710b99091c6e1e268acfc12ff09477c5f..1d5471b3490e3568b5be72ae27a8ec2bc626ab60
  
100644
--- a/test/cctest/test-log.cc
+++ b/test/cctest/test-log.cc
@@ -144,6 +144,26 @@ class LoggerTestHelper : public AllStatic {
  using v8::internal::LoggerTestHelper;


+// Under Linux, we need to check if signals were delivered to avoid false
+// positives.  Under other platforms profiling is done via a high-priority
+// thread, so this case never happen.
+static bool wasSigProfReceived = true;
+#ifdef __linux__
+
+#include <signal.h>
+#include <unistd.h>
+
+struct sigaction oldSigProfHandler;
+
+static void SigProfSignalHandler(int signal, siginfo_t* info, void*  
context) {
+  if (signal != SIGPROF) return;
+  wasSigProfReceived = true;
+  oldSigProfHandler.sa_sigaction(signal, info, context);
+}
+
+#endif  // __linux__
+
+
  static int CheckThatProfilerWorks(int log_pos) {
    Logger::ResumeProfiler();
    CHECK(LoggerTestHelper::IsSamplerActive());
@@ -160,6 +180,18 @@ static int CheckThatProfilerWorks(int log_pos) {
    const char* code_creation = "\ncode-creation,";  // eq. to  
/^code-creation,/
    CHECK_NE(NULL, strstr(buffer.start(), code_creation));

+#ifdef __linux__
+  // Intercept SIGPROF handler to make sure that the test process
+  // had received it. Under load, system can defer it causing test failure.
+  // It is important to execute this after 'ResumeProfiler'.
+  wasSigProfReceived = false;
+  struct sigaction sa;
+  sa.sa_sigaction = SigProfSignalHandler;
+  sigemptyset(&sa.sa_mask);
+  sa.sa_flags = SA_SIGINFO;
+  CHECK_EQ(0, sigaction(SIGPROF, &sa, &oldSigProfHandler));
+#endif  // __linux__
+
    // Force compiler to generate new code by parametrizing source.
    EmbeddedVector<char, 100> script_src;
    i::OS::SNPrintF(script_src,
@@ -170,6 +202,8 @@ static int CheckThatProfilerWorks(int log_pos) {
    const double end_time = i::OS::TimeCurrentMillis() + 200;
    while (i::OS::TimeCurrentMillis() < end_time) {
      CompileAndRunScript(script_src.start());
+    // Yield CPU to give Profiler thread a chance to process ticks.
+    i::OS::Sleep(1);
    }

    Logger::PauseProfiler();
@@ -189,7 +223,8 @@ static int CheckThatProfilerWorks(int log_pos) {
    buffer[log_size] = '\0';
    const char* tick = "\ntick,";
    CHECK_NE(NULL, strstr(buffer.start(), code_creation));
-  CHECK_NE(NULL, strstr(buffer.start(), tick));
+  const bool ticksFound = strstr(buffer.start(), tick) != NULL;
+  CHECK_EQ(wasSigProfReceived, ticksFound);

    return log_pos;
  }



--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to