xpcom/tests/TestDeadlockDetector.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 * vim: sw=4 ts=4 et :
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "mozilla/ArrayUtils.h"
michael@0 8
michael@0 9 #include "prenv.h"
michael@0 10 #include "prerror.h"
michael@0 11 #include "prio.h"
michael@0 12 #include "prproces.h"
michael@0 13
michael@0 14 #include "nsMemory.h"
michael@0 15
michael@0 16 #include "mozilla/CondVar.h"
michael@0 17 #include "mozilla/ReentrantMonitor.h"
michael@0 18 #include "mozilla/Mutex.h"
michael@0 19
michael@0 20 #include "TestHarness.h"
michael@0 21
michael@0 22 using namespace mozilla;
michael@0 23
michael@0 24 static PRThread*
michael@0 25 spawn(void (*run)(void*), void* arg)
michael@0 26 {
michael@0 27 return PR_CreateThread(PR_SYSTEM_THREAD,
michael@0 28 run,
michael@0 29 arg,
michael@0 30 PR_PRIORITY_NORMAL,
michael@0 31 PR_GLOBAL_THREAD,
michael@0 32 PR_JOINABLE_THREAD,
michael@0 33 0);
michael@0 34 }
michael@0 35
michael@0 36 #define PASS() \
michael@0 37 do { \
michael@0 38 passed(__FUNCTION__); \
michael@0 39 return NS_OK; \
michael@0 40 } while (0)
michael@0 41
michael@0 42 #define FAIL(why) \
michael@0 43 do { \
michael@0 44 fail("%s | %s - %s", __FILE__, __FUNCTION__, why); \
michael@0 45 return NS_ERROR_FAILURE; \
michael@0 46 } while (0)
michael@0 47
michael@0 48 //-----------------------------------------------------------------------------
michael@0 49
michael@0 50 static const char* sPathToThisBinary;
michael@0 51 static const char* sAssertBehaviorEnv = "XPCOM_DEBUG_BREAK=abort";
michael@0 52
michael@0 53 class Subprocess
michael@0 54 {
michael@0 55 public:
michael@0 56 // not available until process finishes
michael@0 57 int32_t mExitCode;
michael@0 58 nsCString mStdout;
michael@0 59 nsCString mStderr;
michael@0 60
michael@0 61 Subprocess(const char* aTestName) {
michael@0 62 // set up stdio redirection
michael@0 63 PRFileDesc* readStdin; PRFileDesc* writeStdin;
michael@0 64 PRFileDesc* readStdout; PRFileDesc* writeStdout;
michael@0 65 PRFileDesc* readStderr; PRFileDesc* writeStderr;
michael@0 66 PRProcessAttr* pattr = PR_NewProcessAttr();
michael@0 67
michael@0 68 NS_ASSERTION(pattr, "couldn't allocate process attrs");
michael@0 69
michael@0 70 NS_ASSERTION(PR_SUCCESS == PR_CreatePipe(&readStdin, &writeStdin),
michael@0 71 "couldn't create child stdin pipe");
michael@0 72 NS_ASSERTION(PR_SUCCESS == PR_SetFDInheritable(readStdin, true),
michael@0 73 "couldn't set child stdin inheritable");
michael@0 74 PR_ProcessAttrSetStdioRedirect(pattr, PR_StandardInput, readStdin);
michael@0 75
michael@0 76 NS_ASSERTION(PR_SUCCESS == PR_CreatePipe(&readStdout, &writeStdout),
michael@0 77 "couldn't create child stdout pipe");
michael@0 78 NS_ASSERTION(PR_SUCCESS == PR_SetFDInheritable(writeStdout, true),
michael@0 79 "couldn't set child stdout inheritable");
michael@0 80 PR_ProcessAttrSetStdioRedirect(pattr, PR_StandardOutput, writeStdout);
michael@0 81
michael@0 82 NS_ASSERTION(PR_SUCCESS == PR_CreatePipe(&readStderr, &writeStderr),
michael@0 83 "couldn't create child stderr pipe");
michael@0 84 NS_ASSERTION(PR_SUCCESS == PR_SetFDInheritable(writeStderr, true),
michael@0 85 "couldn't set child stderr inheritable");
michael@0 86 PR_ProcessAttrSetStdioRedirect(pattr, PR_StandardError, writeStderr);
michael@0 87
michael@0 88 // set up argv with test name to run
michael@0 89 char* const newArgv[3] = {
michael@0 90 strdup(sPathToThisBinary),
michael@0 91 strdup(aTestName),
michael@0 92 0
michael@0 93 };
michael@0 94
michael@0 95 // make sure the child will abort if an assertion fails
michael@0 96 NS_ASSERTION(PR_SUCCESS == PR_SetEnv(sAssertBehaviorEnv),
michael@0 97 "couldn't set XPCOM_DEBUG_BREAK env var");
michael@0 98
michael@0 99 PRProcess* proc;
michael@0 100 NS_ASSERTION(proc = PR_CreateProcess(sPathToThisBinary,
michael@0 101 newArgv,
michael@0 102 0, // inherit environment
michael@0 103 pattr),
michael@0 104 "couldn't create process");
michael@0 105 PR_Close(readStdin);
michael@0 106 PR_Close(writeStdout);
michael@0 107 PR_Close(writeStderr);
michael@0 108
michael@0 109 mProc = proc;
michael@0 110 mStdinfd = writeStdin;
michael@0 111 mStdoutfd = readStdout;
michael@0 112 mStderrfd = readStderr;
michael@0 113
michael@0 114 free(newArgv[0]);
michael@0 115 free(newArgv[1]);
michael@0 116 PR_DestroyProcessAttr(pattr);
michael@0 117 }
michael@0 118
michael@0 119 void RunToCompletion(uint32_t aWaitMs)
michael@0 120 {
michael@0 121 PR_Close(mStdinfd);
michael@0 122
michael@0 123 PRPollDesc pollfds[2];
michael@0 124 int32_t nfds;
michael@0 125 bool stdoutOpen = true, stderrOpen = true;
michael@0 126 char buf[4096];
michael@0 127
michael@0 128 PRIntervalTime now = PR_IntervalNow();
michael@0 129 PRIntervalTime deadline = now + PR_MillisecondsToInterval(aWaitMs);
michael@0 130
michael@0 131 while ((stdoutOpen || stderrOpen) && now < deadline) {
michael@0 132 nfds = 0;
michael@0 133 if (stdoutOpen) {
michael@0 134 pollfds[nfds].fd = mStdoutfd;
michael@0 135 pollfds[nfds].in_flags = PR_POLL_READ;
michael@0 136 pollfds[nfds].out_flags = 0;
michael@0 137 ++nfds;
michael@0 138 }
michael@0 139 if (stderrOpen) {
michael@0 140 pollfds[nfds].fd = mStderrfd;
michael@0 141 pollfds[nfds].in_flags = PR_POLL_READ;
michael@0 142 pollfds[nfds].out_flags = 0;
michael@0 143 ++nfds;
michael@0 144 }
michael@0 145
michael@0 146 int32_t rv = PR_Poll(pollfds, nfds, deadline - now);
michael@0 147 NS_ASSERTION(0 <= rv, PR_ErrorToName(PR_GetError()));
michael@0 148
michael@0 149 if (0 == rv) { // timeout
michael@0 150 fputs("(timed out!)\n", stderr);
michael@0 151 Finish(false); // abnormal
michael@0 152 return;
michael@0 153 }
michael@0 154
michael@0 155 for (int32_t i = 0; i < nfds; ++i) {
michael@0 156 if (!pollfds[i].out_flags)
michael@0 157 continue;
michael@0 158
michael@0 159 bool isStdout = mStdoutfd == pollfds[i].fd;
michael@0 160 int32_t len = 0;
michael@0 161
michael@0 162 if (PR_POLL_READ & pollfds[i].out_flags) {
michael@0 163 len = PR_Read(pollfds[i].fd, buf, sizeof(buf) - 1);
michael@0 164 NS_ASSERTION(0 <= len, PR_ErrorToName(PR_GetError()));
michael@0 165 }
michael@0 166 else if (!(PR_POLL_HUP & pollfds[i].out_flags)) {
michael@0 167 NS_ERROR(PR_ErrorToName(PR_GetError()));
michael@0 168 }
michael@0 169
michael@0 170 if (0 < len) {
michael@0 171 buf[len] = '\0';
michael@0 172 if (isStdout)
michael@0 173 mStdout += buf;
michael@0 174 else
michael@0 175 mStderr += buf;
michael@0 176 }
michael@0 177 else if (isStdout) {
michael@0 178 stdoutOpen = false;
michael@0 179 }
michael@0 180 else {
michael@0 181 stderrOpen = false;
michael@0 182 }
michael@0 183 }
michael@0 184
michael@0 185 now = PR_IntervalNow();
michael@0 186 }
michael@0 187
michael@0 188 if (stdoutOpen)
michael@0 189 fputs("(stdout still open!)\n", stderr);
michael@0 190 if (stderrOpen)
michael@0 191 fputs("(stderr still open!)\n", stderr);
michael@0 192 if (now > deadline)
michael@0 193 fputs("(timed out!)\n", stderr);
michael@0 194
michael@0 195 Finish(!stdoutOpen && !stderrOpen && now <= deadline);
michael@0 196 }
michael@0 197
michael@0 198 private:
michael@0 199 void Finish(bool normalExit) {
michael@0 200 if (!normalExit) {
michael@0 201 PR_KillProcess(mProc);
michael@0 202 mExitCode = -1;
michael@0 203 int32_t dummy;
michael@0 204 PR_WaitProcess(mProc, &dummy);
michael@0 205 }
michael@0 206 else {
michael@0 207 PR_WaitProcess(mProc, &mExitCode); // this had better not block ...
michael@0 208 }
michael@0 209
michael@0 210 PR_Close(mStdoutfd);
michael@0 211 PR_Close(mStderrfd);
michael@0 212 }
michael@0 213
michael@0 214 PRProcess* mProc;
michael@0 215 PRFileDesc* mStdinfd; // writeable
michael@0 216 PRFileDesc* mStdoutfd; // readable
michael@0 217 PRFileDesc* mStderrfd; // readable
michael@0 218 };
michael@0 219
michael@0 220 //-----------------------------------------------------------------------------
michael@0 221 // Harness for checking detector errors
michael@0 222 bool
michael@0 223 CheckForDeadlock(const char* test, const char* const* findTokens)
michael@0 224 {
michael@0 225 Subprocess proc(test);
michael@0 226 proc.RunToCompletion(5000);
michael@0 227
michael@0 228 if (0 == proc.mExitCode)
michael@0 229 return false;
michael@0 230
michael@0 231 int32_t idx = 0;
michael@0 232 for (const char* const* tp = findTokens; *tp; ++tp) {
michael@0 233 const char* const token = *tp;
michael@0 234 #ifdef MOZILLA_INTERNAL_API
michael@0 235 idx = proc.mStderr.Find(token, false, idx);
michael@0 236 #else
michael@0 237 nsCString tokenCString(token);
michael@0 238 idx = proc.mStderr.Find(tokenCString, idx);
michael@0 239 #endif
michael@0 240 if (-1 == idx) {
michael@0 241 printf("(missed token '%s' in output)\n", token);
michael@0 242 puts("----------------------------------\n");
michael@0 243 puts(proc.mStderr.get());
michael@0 244 puts("----------------------------------\n");
michael@0 245 return false;
michael@0 246 }
michael@0 247 idx += strlen(token);
michael@0 248 }
michael@0 249
michael@0 250 return true;
michael@0 251 }
michael@0 252
michael@0 253 //-----------------------------------------------------------------------------
michael@0 254 // Single-threaded sanity tests
michael@0 255
michael@0 256 // Stupidest possible deadlock.
michael@0 257 int
michael@0 258 Sanity_Child()
michael@0 259 {
michael@0 260 mozilla::Mutex m1("dd.sanity.m1");
michael@0 261 m1.Lock();
michael@0 262 m1.Lock();
michael@0 263 return 0; // not reached
michael@0 264 }
michael@0 265
michael@0 266 nsresult
michael@0 267 Sanity()
michael@0 268 {
michael@0 269 const char* const tokens[] = {
michael@0 270 "###!!! ERROR: Potential deadlock detected",
michael@0 271 "=== Cyclical dependency starts at\n--- Mutex : dd.sanity.m1",
michael@0 272 "=== Cycle completed at\n--- Mutex : dd.sanity.m1",
michael@0 273 "###!!! Deadlock may happen NOW!", // better catch these easy cases...
michael@0 274 "###!!! ASSERTION: Potential deadlock detected",
michael@0 275 0
michael@0 276 };
michael@0 277 if (CheckForDeadlock("Sanity", tokens)) {
michael@0 278 PASS();
michael@0 279 } else {
michael@0 280 FAIL("deadlock not detected");
michael@0 281 }
michael@0 282 }
michael@0 283
michael@0 284 // Slightly less stupid deadlock.
michael@0 285 int
michael@0 286 Sanity2_Child()
michael@0 287 {
michael@0 288 mozilla::Mutex m1("dd.sanity2.m1");
michael@0 289 mozilla::Mutex m2("dd.sanity2.m2");
michael@0 290 m1.Lock();
michael@0 291 m2.Lock();
michael@0 292 m1.Lock();
michael@0 293 return 0; // not reached
michael@0 294 }
michael@0 295
michael@0 296 nsresult
michael@0 297 Sanity2()
michael@0 298 {
michael@0 299 const char* const tokens[] = {
michael@0 300 "###!!! ERROR: Potential deadlock detected",
michael@0 301 "=== Cyclical dependency starts at\n--- Mutex : dd.sanity2.m1",
michael@0 302 "--- Next dependency:\n--- Mutex : dd.sanity2.m2",
michael@0 303 "=== Cycle completed at\n--- Mutex : dd.sanity2.m1",
michael@0 304 "###!!! Deadlock may happen NOW!", // better catch these easy cases...
michael@0 305 "###!!! ASSERTION: Potential deadlock detected",
michael@0 306 0
michael@0 307 };
michael@0 308 if (CheckForDeadlock("Sanity2", tokens)) {
michael@0 309 PASS();
michael@0 310 } else {
michael@0 311 FAIL("deadlock not detected");
michael@0 312 }
michael@0 313 }
michael@0 314
michael@0 315
michael@0 316 int
michael@0 317 Sanity3_Child()
michael@0 318 {
michael@0 319 mozilla::Mutex m1("dd.sanity3.m1");
michael@0 320 mozilla::Mutex m2("dd.sanity3.m2");
michael@0 321 mozilla::Mutex m3("dd.sanity3.m3");
michael@0 322 mozilla::Mutex m4("dd.sanity3.m4");
michael@0 323
michael@0 324 m1.Lock();
michael@0 325 m2.Lock();
michael@0 326 m3.Lock();
michael@0 327 m4.Lock();
michael@0 328 m4.Unlock();
michael@0 329 m3.Unlock();
michael@0 330 m2.Unlock();
michael@0 331 m1.Unlock();
michael@0 332
michael@0 333 m4.Lock();
michael@0 334 m1.Lock();
michael@0 335 return 0;
michael@0 336 }
michael@0 337
michael@0 338 nsresult
michael@0 339 Sanity3()
michael@0 340 {
michael@0 341 const char* const tokens[] = {
michael@0 342 "###!!! ERROR: Potential deadlock detected",
michael@0 343 "=== Cyclical dependency starts at\n--- Mutex : dd.sanity3.m1",
michael@0 344 "--- Next dependency:\n--- Mutex : dd.sanity3.m2",
michael@0 345 "--- Next dependency:\n--- Mutex : dd.sanity3.m3",
michael@0 346 "--- Next dependency:\n--- Mutex : dd.sanity3.m4",
michael@0 347 "=== Cycle completed at\n--- Mutex : dd.sanity3.m1",
michael@0 348 "###!!! ASSERTION: Potential deadlock detected",
michael@0 349 0
michael@0 350 };
michael@0 351 if (CheckForDeadlock("Sanity3", tokens)) {
michael@0 352 PASS();
michael@0 353 } else {
michael@0 354 FAIL("deadlock not detected");
michael@0 355 }
michael@0 356 }
michael@0 357
michael@0 358
michael@0 359 int
michael@0 360 Sanity4_Child()
michael@0 361 {
michael@0 362 mozilla::ReentrantMonitor m1("dd.sanity4.m1");
michael@0 363 mozilla::Mutex m2("dd.sanity4.m2");
michael@0 364 m1.Enter();
michael@0 365 m2.Lock();
michael@0 366 m1.Enter();
michael@0 367 return 0;
michael@0 368 }
michael@0 369
michael@0 370 nsresult
michael@0 371 Sanity4()
michael@0 372 {
michael@0 373 const char* const tokens[] = {
michael@0 374 "Re-entering ReentrantMonitor after acquiring other resources",
michael@0 375 "###!!! ERROR: Potential deadlock detected",
michael@0 376 "=== Cyclical dependency starts at\n--- ReentrantMonitor : dd.sanity4.m1",
michael@0 377 "--- Next dependency:\n--- Mutex : dd.sanity4.m2",
michael@0 378 "=== Cycle completed at\n--- ReentrantMonitor : dd.sanity4.m1",
michael@0 379 "###!!! ASSERTION: Potential deadlock detected",
michael@0 380 0
michael@0 381 };
michael@0 382 if (CheckForDeadlock("Sanity4", tokens)) {
michael@0 383 PASS();
michael@0 384 } else {
michael@0 385 FAIL("deadlock not detected");
michael@0 386 }
michael@0 387 }
michael@0 388
michael@0 389 //-----------------------------------------------------------------------------
michael@0 390 // Multithreaded tests
michael@0 391
michael@0 392 mozilla::Mutex* ttM1;
michael@0 393 mozilla::Mutex* ttM2;
michael@0 394
michael@0 395 static void
michael@0 396 TwoThreads_thread(void* arg)
michael@0 397 {
michael@0 398 int32_t m1First = NS_PTR_TO_INT32(arg);
michael@0 399 if (m1First) {
michael@0 400 ttM1->Lock();
michael@0 401 ttM2->Lock();
michael@0 402 ttM2->Unlock();
michael@0 403 ttM1->Unlock();
michael@0 404 }
michael@0 405 else {
michael@0 406 ttM2->Lock();
michael@0 407 ttM1->Lock();
michael@0 408 ttM1->Unlock();
michael@0 409 ttM2->Unlock();
michael@0 410 }
michael@0 411 }
michael@0 412
michael@0 413 int
michael@0 414 TwoThreads_Child()
michael@0 415 {
michael@0 416 ttM1 = new mozilla::Mutex("dd.twothreads.m1");
michael@0 417 ttM2 = new mozilla::Mutex("dd.twothreads.m2");
michael@0 418 if (!ttM1 || !ttM2)
michael@0 419 NS_RUNTIMEABORT("couldn't allocate mutexes");
michael@0 420
michael@0 421 PRThread* t1 = spawn(TwoThreads_thread, (void*) 0);
michael@0 422 PR_JoinThread(t1);
michael@0 423
michael@0 424 PRThread* t2 = spawn(TwoThreads_thread, (void*) 1);
michael@0 425 PR_JoinThread(t2);
michael@0 426
michael@0 427 return 0;
michael@0 428 }
michael@0 429
michael@0 430 nsresult
michael@0 431 TwoThreads()
michael@0 432 {
michael@0 433 const char* const tokens[] = {
michael@0 434 "###!!! ERROR: Potential deadlock detected",
michael@0 435 "=== Cyclical dependency starts at\n--- Mutex : dd.twothreads.m2",
michael@0 436 "--- Next dependency:\n--- Mutex : dd.twothreads.m1",
michael@0 437 "=== Cycle completed at\n--- Mutex : dd.twothreads.m2",
michael@0 438 "###!!! ASSERTION: Potential deadlock detected",
michael@0 439 0
michael@0 440 };
michael@0 441
michael@0 442 if (CheckForDeadlock("TwoThreads", tokens)) {
michael@0 443 PASS();
michael@0 444 } else {
michael@0 445 FAIL("deadlock not detected");
michael@0 446 }
michael@0 447 }
michael@0 448
michael@0 449
michael@0 450 mozilla::Mutex* cndMs[4];
michael@0 451 const uint32_t K = 100000;
michael@0 452
michael@0 453 static void
michael@0 454 ContentionNoDeadlock_thread(void* arg)
michael@0 455 {
michael@0 456 int32_t starti = NS_PTR_TO_INT32(arg);
michael@0 457
michael@0 458 for (uint32_t k = 0; k < K; ++k) {
michael@0 459 for (int32_t i = starti; i < (int32_t) ArrayLength(cndMs); ++i)
michael@0 460 cndMs[i]->Lock();
michael@0 461 // comment out the next two lines for deadlocking fun!
michael@0 462 for (int32_t i = ArrayLength(cndMs) - 1; i >= starti; --i)
michael@0 463 cndMs[i]->Unlock();
michael@0 464
michael@0 465 starti = (starti + 1) % 3;
michael@0 466 }
michael@0 467 }
michael@0 468
michael@0 469 int
michael@0 470 ContentionNoDeadlock_Child()
michael@0 471 {
michael@0 472 PRThread* threads[3];
michael@0 473
michael@0 474 for (uint32_t i = 0; i < ArrayLength(cndMs); ++i)
michael@0 475 cndMs[i] = new mozilla::Mutex("dd.cnd.ms");
michael@0 476
michael@0 477 for (int32_t i = 0; i < (int32_t) ArrayLength(threads); ++i)
michael@0 478 threads[i] = spawn(ContentionNoDeadlock_thread, NS_INT32_TO_PTR(i));
michael@0 479
michael@0 480 for (uint32_t i = 0; i < ArrayLength(threads); ++i)
michael@0 481 PR_JoinThread(threads[i]);
michael@0 482
michael@0 483 for (uint32_t i = 0; i < ArrayLength(cndMs); ++i)
michael@0 484 delete cndMs[i];
michael@0 485
michael@0 486 return 0;
michael@0 487 }
michael@0 488
michael@0 489 nsresult
michael@0 490 ContentionNoDeadlock()
michael@0 491 {
michael@0 492 const char * func = __func__;
michael@0 493 Subprocess proc(func);
michael@0 494 proc.RunToCompletion(60000);
michael@0 495 if (0 != proc.mExitCode) {
michael@0 496 printf("(expected 0 == return code, got %d)\n", proc.mExitCode);
michael@0 497 puts("(output)\n----------------------------------\n");
michael@0 498 puts(proc.mStdout.get());
michael@0 499 puts("----------------------------------\n");
michael@0 500 puts("(error output)\n----------------------------------\n");
michael@0 501 puts(proc.mStderr.get());
michael@0 502 puts("----------------------------------\n");
michael@0 503
michael@0 504 FAIL("deadlock");
michael@0 505 }
michael@0 506 PASS();
michael@0 507 }
michael@0 508
michael@0 509
michael@0 510
michael@0 511 //-----------------------------------------------------------------------------
michael@0 512
michael@0 513 int
michael@0 514 main(int argc, char** argv)
michael@0 515 {
michael@0 516 if (1 < argc) {
michael@0 517 // XXX can we run w/o scoped XPCOM?
michael@0 518 const char* test = argv[1];
michael@0 519 ScopedXPCOM xpcom(test);
michael@0 520 if (xpcom.failed())
michael@0 521 return 1;
michael@0 522
michael@0 523 // running in a spawned process. call the specificed child function.
michael@0 524 if (!strcmp("Sanity", test))
michael@0 525 return Sanity_Child();
michael@0 526 if (!strcmp("Sanity2", test))
michael@0 527 return Sanity2_Child();
michael@0 528 if (!strcmp("Sanity3", test))
michael@0 529 return Sanity3_Child();
michael@0 530 if (!strcmp("Sanity4", test))
michael@0 531 return Sanity4_Child();
michael@0 532
michael@0 533 if (!strcmp("TwoThreads", test))
michael@0 534 return TwoThreads_Child();
michael@0 535 if (!strcmp("ContentionNoDeadlock", test))
michael@0 536 return ContentionNoDeadlock_Child();
michael@0 537
michael@0 538 fail("%s | %s - unknown child test", __FILE__, __FUNCTION__);
michael@0 539 return 2;
michael@0 540 }
michael@0 541
michael@0 542 ScopedXPCOM xpcom("XPCOM deadlock detector correctness (" __FILE__ ")");
michael@0 543 if (xpcom.failed())
michael@0 544 return 1;
michael@0 545
michael@0 546 // in the first invocation of this process. we will be the "driver".
michael@0 547 int rv = 0;
michael@0 548
michael@0 549 sPathToThisBinary = argv[0];
michael@0 550
michael@0 551 if (NS_FAILED(Sanity()))
michael@0 552 rv = 1;
michael@0 553 if (NS_FAILED(Sanity2()))
michael@0 554 rv = 1;
michael@0 555 if (NS_FAILED(Sanity3()))
michael@0 556 rv = 1;
michael@0 557 if (NS_FAILED(Sanity4()))
michael@0 558 rv = 1;
michael@0 559
michael@0 560 if (NS_FAILED(TwoThreads()))
michael@0 561 rv = 1;
michael@0 562 if (NS_FAILED(ContentionNoDeadlock()))
michael@0 563 rv = 1;
michael@0 564
michael@0 565 return rv;
michael@0 566 }

mercurial