summaryrefslogtreecommitdiffstats
path: root/Tools/WebKitTestRunner/win/TestControllerWin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/WebKitTestRunner/win/TestControllerWin.cpp')
-rw-r--r--Tools/WebKitTestRunner/win/TestControllerWin.cpp66
1 files changed, 60 insertions, 6 deletions
diff --git a/Tools/WebKitTestRunner/win/TestControllerWin.cpp b/Tools/WebKitTestRunner/win/TestControllerWin.cpp
index 5af5503..6201cf7 100644
--- a/Tools/WebKitTestRunner/win/TestControllerWin.cpp
+++ b/Tools/WebKitTestRunner/win/TestControllerWin.cpp
@@ -38,6 +38,13 @@ using namespace std;
namespace WTR {
+static HANDLE webProcessCrashingEvent;
+static const char webProcessCrashingEventName[] = "WebKitTestRunner.WebProcessCrashing";
+// This is the longest we'll wait (in seconds) for the web process to finish crashing and a crash
+// log to be saved. This interval should be just a tiny bit longer than it will ever reasonably
+// take to save a crash log.
+static const double maximumWaitForWebProcessToCrash = 60;
+
#ifdef DEBUG_ALL
const LPWSTR testPluginDirectoryName = L"TestNetscapePlugin_Debug";
const char* injectedBundleDLL = "\\InjectedBundle_debug.dll";
@@ -96,6 +103,11 @@ void TestController::notifyDone()
void TestController::platformInitialize()
{
+ // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
+ // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
+ // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
+ ::SetErrorMode(0);
+
::SetUnhandledExceptionFilter(exceptionFilter);
_setmode(1, _O_BINARY);
@@ -104,6 +116,8 @@ void TestController::platformInitialize()
// Add the QuickTime dll directory to PATH or QT 7.6 will fail to initialize on systems
// linked with older versions of qtmlclientlib.dll.
addQTDirToPATH();
+
+ webProcessCrashingEvent = ::CreateEventA(0, FALSE, FALSE, webProcessCrashingEventName);
}
void TestController::initializeInjectedBundlePath()
@@ -124,19 +138,26 @@ void TestController::initializeTestPluginDirectory()
m_testPluginDirectory.adopt(WKStringCreateWithCFString(testPluginDirectoryPath.get()));
}
-void TestController::platformRunUntil(bool& done, double timeout)
+enum RunLoopResult { TimedOut, ObjectSignaled, ConditionSatisfied };
+
+static RunLoopResult runRunLoopUntil(bool& condition, HANDLE object, double timeout)
{
DWORD end = ::GetTickCount() + timeout * 1000;
- while (!done) {
+ while (!condition) {
DWORD now = ::GetTickCount();
if (now > end)
- return;
+ return TimedOut;
- DWORD result = ::MsgWaitForMultipleObjectsEx(0, 0, end - now, QS_ALLINPUT, 0);
+ DWORD objectCount = object ? 1 : 0;
+ const HANDLE* objects = object ? &object : 0;
+ DWORD result = ::MsgWaitForMultipleObjectsEx(objectCount, objects, end - now, QS_ALLINPUT, MWMO_INPUTAVAILABLE);
if (result == WAIT_TIMEOUT)
- return;
+ return TimedOut;
- ASSERT(result == WAIT_OBJECT_0);
+ if (objectCount && result >= WAIT_OBJECT_0 && result < WAIT_OBJECT_0 + objectCount)
+ return ObjectSignaled;
+
+ ASSERT(result == WAIT_OBJECT_0 + objectCount);
// There are messages in the queue. Process them.
MSG msg;
while (::PeekMessageW(&msg, 0, 0, 0, PM_REMOVE)) {
@@ -144,12 +165,45 @@ void TestController::platformRunUntil(bool& done, double timeout)
::DispatchMessageW(&msg);
}
}
+
+ return ConditionSatisfied;
+}
+
+void TestController::platformRunUntil(bool& done, double timeout)
+{
+ RunLoopResult result = runRunLoopUntil(done, webProcessCrashingEvent, timeout);
+ if (result == TimedOut || result == ConditionSatisfied)
+ return;
+ ASSERT(result == ObjectSignaled);
+
+ // The web process is crashing. A crash log might be being saved, which can take a long
+ // time, and we don't want to time out while that happens.
+
+ // First, let the test harness know this happened so it won't think we've hung. But
+ // make sure we don't exit just yet!
+ m_shouldExitWhenWebProcessCrashes = false;
+ processDidCrash();
+ m_shouldExitWhenWebProcessCrashes = true;
+
+ // Then spin a run loop until it finishes crashing to give time for a crash log to be saved. If
+ // it takes too long for a crash log to be saved, we'll just give up.
+ bool neverSetCondition = false;
+ result = runRunLoopUntil(neverSetCondition, 0, maximumWaitForWebProcessToCrash);
+ ASSERT_UNUSED(result, result == TimedOut);
+ exit(1);
+}
+
+static WKRetainPtr<WKStringRef> toWK(const char* string)
+{
+ return WKRetainPtr<WKStringRef>(AdoptWK, WKStringCreateWithUTF8CString(string));
}
void TestController::platformInitializeContext()
{
// FIXME: Make DRT pass with Windows native controls. <http://webkit.org/b/25592>
WKContextSetShouldPaintNativeControls(m_context.get(), false);
+
+ WKContextSetInitializationUserDataForInjectedBundle(m_context.get(), toWK(webProcessCrashingEventName).get());
}
void TestController::runModal(PlatformWebView*)