[gardening] Lower core rlimit to 0 if test is expected to crash.

We do not archive core dumps generated by tests that are expected
to crash - so there is no need to generate those dumps.

It seems that generating core dumps is very slow on Mac and causes
timeouts.

Fixes #35275

Remove Timeout expectations from Crashing tests

Change-Id: I36c89fd583a6a94521560544163f02414cbbf41a
Reviewed-on: https://dart-review.googlesource.com/c/85680
Commit-Queue: Vyacheslav Egorov <vegorov@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index aa10c51..339a63ed 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -1011,7 +1011,11 @@
   }
   DartUtils::SetEnvironment(Options::environment());
 
-  InitializeCrashpadClient();
+  if (Options::suppress_core_dump()) {
+    Platform::SetCoreDumpResourceLimit(0);
+  } else {
+    InitializeCrashpadClient();
+  }
 
   Loader::InitOnce();
 
diff --git a/runtime/bin/main_options.h b/runtime/bin/main_options.h
index 1c56d0b..5a0377e 100644
--- a/runtime/bin/main_options.h
+++ b/runtime/bin/main_options.h
@@ -41,7 +41,8 @@
   V(short_socket_read, short_socket_read)                                      \
   V(short_socket_write, short_socket_write)                                    \
   V(disable_exit, exit_disabled)                                               \
-  V(preview_dart_2, nop_option)
+  V(preview_dart_2, nop_option)                                                \
+  V(suppress_core_dump, suppress_core_dump)
 
 // Boolean flags that have a short form.
 #define SHORT_BOOL_OPTIONS_LIST(V)                                             \
diff --git a/runtime/bin/platform.h b/runtime/bin/platform.h
index d174902..76712a6 100644
--- a/runtime/bin/platform.h
+++ b/runtime/bin/platform.h
@@ -90,6 +90,8 @@
 
   static DART_NORETURN void Exit(int exit_code);
 
+  static void SetCoreDumpResourceLimit(int value);
+
  private:
   // The path to the executable.
   static const char* executable_name_;
diff --git a/runtime/bin/platform_android.cc b/runtime/bin/platform_android.cc
index a7afafe..cd1efd7 100644
--- a/runtime/bin/platform_android.cc
+++ b/runtime/bin/platform_android.cc
@@ -10,6 +10,7 @@
 #include <errno.h>        // NOLINT
 #include <signal.h>       // NOLINT
 #include <string.h>       // NOLINT
+#include <sys/resource.h>
 #include <sys/utsname.h>  // NOLINT
 #include <unistd.h>       // NOLINT
 
@@ -167,6 +168,11 @@
   exit(exit_code);
 }
 
+void Platform::SetCoreDumpResourceLimit(int value) {
+  rlimit limit = {static_cast<rlim_t>(value), static_cast<rlim_t>(value)};
+  setrlimit(RLIMIT_CORE, &limit);
+}
+
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/platform_fuchsia.cc b/runtime/bin/platform_fuchsia.cc
index 58aecb1..7893f14 100644
--- a/runtime/bin/platform_fuchsia.cc
+++ b/runtime/bin/platform_fuchsia.cc
@@ -152,6 +152,10 @@
   exit(exit_code);
 }
 
+void Platform::SetCoreDumpResourceLimit(int value) {
+  // Not supported.
+}
+
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/platform_linux.cc b/runtime/bin/platform_linux.cc
index a8dccc5..260a900 100644
--- a/runtime/bin/platform_linux.cc
+++ b/runtime/bin/platform_linux.cc
@@ -10,6 +10,7 @@
 #include <errno.h>        // NOLINT
 #include <signal.h>       // NOLINT
 #include <string.h>       // NOLINT
+#include <sys/resource.h>  // NOLINT
 #include <sys/utsname.h>  // NOLINT
 #include <unistd.h>       // NOLINT
 
@@ -167,6 +168,11 @@
   exit(exit_code);
 }
 
+void Platform::SetCoreDumpResourceLimit(int value) {
+  rlimit limit = {static_cast<rlim_t>(value), static_cast<rlim_t>(value)};
+  setrlimit(RLIMIT_CORE, &limit);
+}
+
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/platform_macos.cc b/runtime/bin/platform_macos.cc
index 1cf7f46..c41e8b2 100644
--- a/runtime/bin/platform_macos.cc
+++ b/runtime/bin/platform_macos.cc
@@ -16,6 +16,7 @@
 #include <mach-o/dyld.h>
 #include <signal.h>       // NOLINT
 #include <string.h>       // NOLINT
+#include <sys/resource.h>  // NOLINT
 #include <sys/sysctl.h>   // NOLINT
 #include <sys/types.h>    // NOLINT
 #include <sys/utsname.h>  // NOLINT
@@ -256,6 +257,11 @@
   exit(exit_code);
 }
 
+void Platform::SetCoreDumpResourceLimit(int value) {
+  rlimit limit = {static_cast<rlim_t>(value), static_cast<rlim_t>(value)};
+  setrlimit(RLIMIT_CORE, &limit);
+}
+
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/platform_win.cc b/runtime/bin/platform_win.cc
index 069b9e5..b0fd774 100644
--- a/runtime/bin/platform_win.cc
+++ b/runtime/bin/platform_win.cc
@@ -287,6 +287,10 @@
   ::ExitProcess(exit_code);
 }
 
+void Platform::SetCoreDumpResourceLimit(int value) {
+  // Not supported.
+}
+
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/run_vm_tests.cc b/runtime/bin/run_vm_tests.cc
index f488063..703f57f 100644
--- a/runtime/bin/run_vm_tests.cc
+++ b/runtime/bin/run_vm_tests.cc
@@ -210,6 +210,15 @@
   delete isolate_data;
 }
 
+void ShiftArgs(int* argc, const char** argv) {
+  // Remove the first flag from the list by shifting all arguments down.
+  for (intptr_t i = 1; i < *argc - 1; i++) {
+    argv[i] = argv[i + 1];
+  }
+  argv[*argc - 1] = nullptr;
+  (*argc)--;
+}
+
 static int Main(int argc, const char** argv) {
   // Flags being passed to the Dart VM.
   int dart_argc = 0;
@@ -221,8 +230,6 @@
     return 1;
   }
 
-  dart::bin::InitializeCrashpadClient();
-
   // Save the console state so we can restore it later.
   dart::bin::Console::SaveConfig();
 
@@ -247,7 +254,19 @@
 
   int arg_pos = 1;
   bool start_kernel_isolate = false;
-  if (strstr(argv[arg_pos], "--dfe") == argv[arg_pos]) {
+  bool suppress_core_dump = false;
+  if (strcmp(argv[arg_pos], "--suppress-core-dump") == 0) {
+    suppress_core_dump = true;
+    ShiftArgs(&argc, argv);
+  }
+
+  if (suppress_core_dump) {
+    bin::Platform::SetCoreDumpResourceLimit(0);
+  } else {
+    bin::InitializeCrashpadClient();
+  }
+
+  if (strncmp(argv[arg_pos], "--dfe", strlen("--dfe")) == 0) {
     const char* delim = strstr(argv[arg_pos], "=");
     if (delim == NULL || strlen(delim + 1) == 0) {
       bin::Log::PrintErr("Invalid value for the option: %s\n", argv[arg_pos]);
@@ -255,13 +274,8 @@
       return 1;
     }
     kernel_snapshot = strdup(delim + 1);
-    // Remove this flag from the list by shifting all arguments down.
-    for (intptr_t i = arg_pos; i < argc - 1; i++) {
-      argv[i] = argv[i + 1];
-    }
-    argv[argc - 1] = nullptr;
-    argc--;
     start_kernel_isolate = true;
+    ShiftArgs(&argc, argv);
   }
 
   if (arg_pos == argc - 1 && strcmp(argv[arg_pos], "--benchmarks") == 0) {
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 73d90eb..219da39 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -23,20 +23,6 @@
 dart/slow_path_shared_stub_test: Pass, Slow # Uses --shared-slow-path-triggers-gc flag.
 dart/stack_overflow_shared_test: Pass, Slow # Uses --shared-slow-path-triggers-gc flag.
 
-[ $system == macos ]
-cc/AllocGeneric_Overflow: Timeout # On MacOS the segfault handler can hang, see http://dartbug.com/35275
-cc/ArrayNew_Overflow_Crash: Timeout # On MacOS the segfault handler can hang, see http://dartbug.com/35275
-cc/Class_ComputeEndTokenPos: Timeout # On MacOS the segfault handler can hang, see http://dartbug.com/35275
-cc/CodeImmutability: Timeout # On MacOS the segfault handler can hang, see http://dartbug.com/35275
-cc/DartGeneratedArrayLiteralMessages: Timeout # On MacOS the segfault handler can hang, see http://dartbug.com/35275
-cc/FullSnapshot1: Timeout # On MacOS the segfault handler can hang, see http://dartbug.com/35275
-cc/IsolateReload_PendingConstructorCall_AbstractToConcrete: Timeout # On MacOS the segfault handler can hang, see http://dartbug.com/35275
-cc/IsolateReload_PendingConstructorCall_ConcreteToAbstract: Timeout # On MacOS the segfault handler can hang, see http://dartbug.com/35275
-cc/IsolateReload_PendingStaticCall_NSMToDefined: Timeout # On MacOS the segfault handler can hang, see http://dartbug.com/35275
-cc/SNPrint_BadArgs: Timeout # On MacOS the segfault handler can hang, see http://dartbug.com/35275
-cc/SourceReport_Coverage_UnusedClass_ForceCompileError: Timeout # On MacOS the segfault handler can hang, see http://dartbug.com/35275
-cc/FullSnapshot1: Timeout # On MacOS the segfault handler can hang, see http://dartbug.com/35275
-
 [ $mode == debug ]
 dart/appjit_cha_deopt_test: Pass, Slow # Quite slow in debug mode, uses --optimization-counter-threshold=100
 
diff --git a/tools/testing/dart/runtime_configuration.dart b/tools/testing/dart/runtime_configuration.dart
index ff8efbb..8330b51 100644
--- a/tools/testing/dart/runtime_configuration.dart
+++ b/tools/testing/dart/runtime_configuration.dart
@@ -81,7 +81,8 @@
       TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
-      Map<String, String> environmentOverrides) {
+      Map<String, String> environmentOverrides,
+      bool isCrashExpected) {
     // TODO(ahe): Make this method abstract.
     throw "Unimplemented runtime '$runtimeType'";
   }
@@ -99,7 +100,8 @@
       TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
-      Map<String, String> environmentOverrides) {
+      Map<String, String> environmentOverrides,
+      bool isCrashExpected) {
     return <Command>[];
   }
 }
@@ -125,7 +127,8 @@
       TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
-      Map<String, String> environmentOverrides) {
+      Map<String, String> environmentOverrides,
+      bool isCrashExpected) {
     // TODO(ahe): Avoid duplication of this method between d8 and jsshell.
     checkArtifact(artifact);
     return [
@@ -147,7 +150,8 @@
       TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
-      Map<String, String> environmentOverrides) {
+      Map<String, String> environmentOverrides,
+      bool isCrashExpected) {
     checkArtifact(artifact);
     return [
       Command.jsCommandLine(
@@ -205,7 +209,8 @@
       TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
-      Map<String, String> environmentOverrides) {
+      Map<String, String> environmentOverrides,
+      bool isCrashExpected) {
     String script = artifact.filename;
     String type = artifact.mimeType;
     if (script != null &&
@@ -215,7 +220,9 @@
         type != 'application/kernel-ir-fully-linked') {
       throw "Dart VM cannot run files of type '$type'.";
     }
-
+    if (isCrashExpected) {
+      arguments.insert(0, '--suppress-core-dump');
+    }
     String executable = suite.dartVmBinaryFileName;
     if (type == 'application/kernel-ir-fully-linked') {
       executable = suite.dartVmExecutableFileName;
@@ -230,7 +237,8 @@
       TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
-      Map<String, String> environmentOverrides) {
+      Map<String, String> environmentOverrides,
+      bool isCrashExpected) {
     String script = artifact.filename;
     String type = artifact.mimeType;
     if (script != null &&
@@ -252,7 +260,8 @@
       TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
-      Map<String, String> environmentOverrides) {
+      Map<String, String> environmentOverrides,
+      bool isCrashExpected) {
     String script = artifact.filename;
     String type = artifact.mimeType;
     if (script != null && type != 'application/dart-precompiled') {
@@ -279,7 +288,8 @@
       TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
-      Map<String, String> environmentOverrides) {
+      Map<String, String> environmentOverrides,
+      bool isCrashExpected) {
     String script = artifact.filename;
     String type = artifact.mimeType;
     if (script != null && type != 'application/dart-precompiled') {
@@ -315,7 +325,8 @@
       TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
-      Map<String, String> environmentOverrides) {
+      Map<String, String> environmentOverrides,
+      bool isCrashExpected) {
     String executable = suite.dartVmBinaryFileName;
     return selfCheckers
         .map((String tester) => Command.vmBatch(
@@ -336,7 +347,8 @@
       TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
-      Map<String, String> environmentOverrides) {
+      Map<String, String> environmentOverrides,
+      bool isCrashExpected) {
     throw "Unimplemented runtime '$runtimeType'";
   }
 }
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index 4a76a66..0666aff 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -483,6 +483,9 @@
   }
 
   void _addTest(ExpectationSet testExpectations, String testName) {
+    var fullName = 'cc/$testName';
+    var expectations = testExpectations.expectations(fullName);
+
     var args = configuration.standardOptions.toList();
     if (configuration.compilerConfiguration.previewDart2) {
       final dfePath = new Path("$buildDir/gen/kernel-service.dart.snapshot")
@@ -491,13 +494,14 @@
       // '--dfe' has to be the first argument for run_vm_test to pick it up.
       args.insert(0, '--dfe=$dfePath');
     }
+    if (expectations.contains(Expectation.crash)) {
+      args.insert(0, '--suppress-core-dump');
+    }
 
     args.add(testName);
 
     var command = Command.process(
         'run_vm_unittest', targetRunnerPath, args, environmentOverrides);
-    var fullName = 'cc/$testName';
-    var expectations = testExpectations.expectations(fullName);
     enqueueNewTestCase(fullName, [command], expectations);
   }
 
@@ -828,15 +832,16 @@
         allVmOptions = vmOptions.toList()..addAll(extraVmOptions);
       }
 
-      var commands =
-          makeCommands(info, vmOptionsVariant, allVmOptions, commonArguments);
       var expectations = testExpectations.expectations(testName);
+      var isCrashExpected = expectations.contains(Expectation.crash);
+      var commands = makeCommands(info, vmOptionsVariant, allVmOptions,
+          commonArguments, isCrashExpected);
       enqueueNewTestCase(testName, commands, expectations, info);
     }
   }
 
   List<Command> makeCommands(TestInformation info, int vmOptionsVariant,
-      List<String> vmOptions, List<String> args) {
+      List<String> vmOptions, List<String> args, bool isCrashExpected) {
     var commands = <Command>[];
     var compilerConfiguration = configuration.compilerConfiguration;
     var sharedOptions = info.optionsFromFile['sharedOptions'] as List<String>;
@@ -897,8 +902,8 @@
     }
 
     return commands
-      ..addAll(configuration.runtimeConfiguration.computeRuntimeCommands(
-          this, compilationArtifact, runtimeArguments, environment));
+      ..addAll(configuration.runtimeConfiguration.computeRuntimeCommands(this,
+          compilationArtifact, runtimeArguments, environment, isCrashExpected));
   }
 
   CreateTest makeTestCaseCreator(Map<String, dynamic> optionsFromFile) {