Version 2.14.0-94.0.dev

Merge commit '7eb280566593eb577f0a75066f25f02271cfe417' into 'dev'
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/function_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/function_test.dart
new file mode 100644
index 0000000..77f3d6b
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/function_test.dart
@@ -0,0 +1,95 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(FunctionTest);
+  });
+}
+
+@reflectiveTest
+class FunctionTest extends PubPackageResolutionTest {
+  test_genericFunction_upwards() async {
+    await assertNoErrorsInCode('''
+void foo<T>(T x, T y) {}
+
+f() {
+  foo(1, 2);
+}
+''');
+    assertTypeArgumentTypes(
+      findNode.methodInvocation('foo('),
+      ['int'],
+    );
+  }
+
+  test_genericFunction_upwards_missingRequiredArgument() async {
+    await assertErrorsInCode('''
+void foo<T>({required T x, required T y}) {}
+
+f() {
+  foo(x: 1);
+}
+''', [
+      error(CompileTimeErrorCode.MISSING_REQUIRED_ARGUMENT, 54, 3),
+    ]);
+    assertTypeArgumentTypes(
+      findNode.methodInvocation('foo('),
+      ['int'],
+    );
+  }
+
+  test_genericFunction_upwards_notEnoughPositionalArguments() async {
+    await assertErrorsInCode('''
+void foo<T>(T x, T y) {}
+
+f() {
+  foo(1);
+}
+''', [
+      error(CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS, 37, 3),
+    ]);
+    assertTypeArgumentTypes(
+      findNode.methodInvocation('foo('),
+      ['int'],
+    );
+  }
+
+  test_genericFunction_upwards_tooManyPositionalArguments() async {
+    await assertErrorsInCode('''
+void foo<T>(T x, T y) {}
+
+f() {
+  foo(1, 2, 3);
+}
+''', [
+      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 44, 1),
+    ]);
+    assertTypeArgumentTypes(
+      findNode.methodInvocation('foo('),
+      ['int'],
+    );
+  }
+
+  test_genericFunction_upwards_undefinedNamedParameter() async {
+    await assertErrorsInCode('''
+void foo<T>(T x, T y) {}
+
+f() {
+  foo(1, 2, z: 3);
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER, 44, 1),
+    ]);
+    assertTypeArgumentTypes(
+      findNode.methodInvocation('foo('),
+      ['int'],
+    );
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/test_all.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/test_all.dart
index a998d76..17dfe68 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/test_all.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/test_all.dart
@@ -9,6 +9,7 @@
 import 'equality_expressions_test.dart' as equality_expressions;
 import 'extension_methods_test.dart' as extension_methods;
 import 'function_expression_test.dart' as function_expression;
+import 'function_test.dart' as function;
 import 'list_literal_test.dart' as list_literal;
 import 'local_variable_test.dart' as local_variable;
 import 'logical_boolean_expressions_test.dart' as logical_boolean_expressions;
@@ -25,6 +26,7 @@
     conditional_expression.main();
     equality_expressions.main();
     extension_methods.main();
+    function.main();
     function_expression.main();
     list_literal.main();
     local_variable.main();
diff --git a/pkg/analyzer/test/src/diagnostics/return_of_invalid_type_test.dart b/pkg/analyzer/test/src/diagnostics/return_of_invalid_type_test.dart
index d1f7457..841251e 100644
--- a/pkg/analyzer/test/src/diagnostics/return_of_invalid_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/return_of_invalid_type_test.dart
@@ -72,6 +72,16 @@
     ]);
   }
 
+  test_function_async_block_Future_String__to_Future_int() async {
+    await assertErrorsInCode('''
+Future<int> f(Future<String> a) async {
+  return a;
+}
+''', [
+      error(CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 49, 1),
+    ]);
+  }
+
   test_function_async_block_Future_void() async {
     await assertNoErrorsInCode('''
 void f1(Future<void> a) async { return a; }
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index 2c79318..81ffb05 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -472,62 +472,6 @@
     ]);
   }
 
-  test_functionModifiers_async() async {
-    await assertErrorsInCode('''
-import 'dart:math' show Random;
-
-dynamic x;
-
-foo1() async => x;
-Future foo2() async => x;
-Future<int> foo3() async => x;
-Future<int> foo4() async => new Future<int>.value(x);
-Future<int> foo5() async => new Future<String>.value(x);
-
-bar1() async { return x; }
-Future bar2() async { return x; }
-Future<int> bar3() async { return x; }
-Future<int> bar4() async {
-  return new Future<int>.value(x);
-}
-Future<int> bar5() async {
-  return new Future<String>.value(x);
-}
-
-int y;
-Future<int> z;
-
-baz() async {
-  int a = await x;
-  int b = await y;
-  int c = await z;
-  String d = await z;
-}
-
-Future<bool> get issue_ddc_264 async {
-  await 42;
-  if (new Random().nextBool()) {
-    return true;
-  } else {
-    return new Future<bool>.value(false);
-  }
-}
-
-
-Future<String> issue_sdk_26404() async {
-  return ((1 > 0) ? new Future<String>.value('hello') : "world");
-}
-''', [
-      error(CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 203, 27),
-      error(CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 433, 27),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 508, 1),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 527, 1),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 546, 1),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 568, 1),
-      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 572, 7),
-    ]);
-  }
-
   test_functionTypingAndSubtyping_classes() async {
     await assertErrorsInCode('''
 class A {}
@@ -1679,27 +1623,6 @@
     ]);
   }
 
-  test_functionTypingAndSubtyping_uninferredClosure() async {
-    await assertErrorsInCode('''
-typedef num Num2Num(num x);
-void main() {
-  Num2Num g = (int x) { return x; };
-  print(g(42));
-}
-''', [
-      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 56, 21),
-    ]);
-  }
-
-  test_functionTypingAndSubtyping_void() async {
-    await assertNoErrorsInCode('''
-class A {
-  void bar() => null;
-  void foo() => bar(); // allowed
-}
-''');
-  }
-
   test_genericClassMethodOverride() async {
     await assertErrorsInCode('''
 class A {}
@@ -1721,50 +1644,6 @@
     ]);
   }
 
-  test_genericFunctionWrongNumberOfArguments() async {
-    await assertErrorsInCode(r'''
-T foo<T>(T x, T y) => x;
-T bar<T>({T x, T y}) => x;
-
-main() {
-  String x;
-  // resolving these shouldn't crash.
-  foo(1, 2, 3);
-  x = foo('1', '2', '3');
-  foo(1);
-  x = foo('1');
-  x = foo(1, 2, 3);
-  x = foo(1);
-
-  // named arguments
-  bar(y: 1, x: 2, z: 3);
-  x = bar(z: '1', x: '2', y: '3');
-  bar(y: 1);
-  x = bar(x: '1', z: 42);
-  x = bar(y: 1, x: 2, z: 3);
-  x = bar(x: 1);
-}
-''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 71, 1),
-      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 124, 1),
-      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 148, 3),
-      error(CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS, 159, 3),
-      error(CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS, 173, 5),
-      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 196, 1),
-      error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 190, 1),
-      error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 193, 1),
-      error(CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS, 209, 3),
-      error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 210, 1),
-      error(CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER, 254, 1),
-      error(CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER, 271, 1),
-      error(CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER, 327, 1),
-      error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 348, 1),
-      error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 354, 1),
-      error(CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER, 357, 1),
-      error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 377, 1),
-    ]);
-  }
-
   test_genericMethodOverride() async {
     await assertNoErrorsInCode('''
 class Future<T> {
diff --git a/pkg/vm/lib/transformations/ffi.dart b/pkg/vm/lib/transformations/ffi.dart
index 558f4da..a4c6fd4 100644
--- a/pkg/vm/lib/transformations/ffi.dart
+++ b/pkg/vm/lib/transformations/ffi.dart
@@ -784,6 +784,25 @@
         InterfaceType(compoundClass, Nullability.legacy),
         SubtypeCheckMode.ignoringNullabilities);
   }
+
+  Expression getCompoundTypedDataBaseField(
+      Expression receiver, int fileOffset) {
+    return PropertyGet(
+        receiver, compoundTypedDataBaseField.name, compoundTypedDataBaseField)
+      ..fileOffset = fileOffset;
+  }
+
+  Expression getArrayTypedDataBaseField(Expression receiver,
+      [int fileOffset = TreeNode.noOffset]) {
+    return PropertyGet(
+        receiver, arrayTypedDataBaseField.name, arrayTypedDataBaseField)
+      ..fileOffset = fileOffset;
+  }
+
+  Expression multiply(Expression a, Expression b) {
+    return MethodInvocation(
+        a, numMultiplication.name, Arguments([b]), numMultiplication);
+  }
 }
 
 /// Checks if any library depends on dart:ffi.
diff --git a/pkg/vm/lib/transformations/ffi_definitions.dart b/pkg/vm/lib/transformations/ffi_definitions.dart
index e69b8a1..f841be3 100644
--- a/pkg/vm/lib/transformations/ffi_definitions.dart
+++ b/pkg/vm/lib/transformations/ffi_definitions.dart
@@ -1033,11 +1033,8 @@
               ? transformer.loadUnalignedMethods
               : transformer.loadMethods)[nativeType],
           Arguments([
-            PropertyGet(
-                ThisExpression(),
-                transformer.compoundTypedDataBaseField.name,
-                transformer.compoundTypedDataBaseField)
-              ..fileOffset = fileOffset,
+            transformer.getCompoundTypedDataBaseField(
+                ThisExpression(), fileOffset),
             transformer.runtimeBranchOnLayout(offsets)
           ]))
         ..fileOffset = fileOffset);
@@ -1060,11 +1057,8 @@
               ? transformer.storeUnalignedMethods
               : transformer.storeMethods)[nativeType],
           Arguments([
-            PropertyGet(
-                ThisExpression(),
-                transformer.compoundTypedDataBaseField.name,
-                transformer.compoundTypedDataBaseField)
-              ..fileOffset = fileOffset,
+            transformer.getCompoundTypedDataBaseField(
+                ThisExpression(), fileOffset),
             transformer.runtimeBranchOnLayout(offsets),
             VariableGet(argument)
           ]))
@@ -1103,11 +1097,8 @@
             StaticInvocation(
                 transformer.loadMethods[NativeType.kIntptr],
                 Arguments([
-                  PropertyGet(
-                      ThisExpression(),
-                      transformer.compoundTypedDataBaseField.name,
-                      transformer.compoundTypedDataBaseField)
-                    ..fileOffset = fileOffset,
+                  transformer.getCompoundTypedDataBaseField(
+                      ThisExpression(), fileOffset),
                   transformer.runtimeBranchOnLayout(offsets)
                 ]))
               ..fileOffset = fileOffset
@@ -1132,11 +1123,8 @@
       ReturnStatement(StaticInvocation(
           transformer.storeMethods[NativeType.kIntptr],
           Arguments([
-            PropertyGet(
-                ThisExpression(),
-                transformer.compoundTypedDataBaseField.name,
-                transformer.compoundTypedDataBaseField)
-              ..fileOffset = fileOffset,
+            transformer.getCompoundTypedDataBaseField(
+                ThisExpression(), fileOffset),
             transformer.runtimeBranchOnLayout(offsets),
             PropertyGet(VariableGet(argument), transformer.addressGetter.name,
                 transformer.addressGetter)
@@ -1183,11 +1171,8 @@
         constructor,
         Arguments([
           transformer.typedDataBaseOffset(
-              PropertyGet(
-                  ThisExpression(),
-                  transformer.compoundTypedDataBaseField.name,
-                  transformer.compoundTypedDataBaseField)
-                ..fileOffset = fileOffset,
+              transformer.getCompoundTypedDataBaseField(
+                  ThisExpression(), fileOffset),
               transformer.runtimeBranchOnLayout(offsets),
               transformer.runtimeBranchOnLayout(size),
               dartType,
@@ -1212,17 +1197,11 @@
       ReturnStatement(StaticInvocation(
           transformer.memCopy,
           Arguments([
-            PropertyGet(
-                ThisExpression(),
-                transformer.compoundTypedDataBaseField.name,
-                transformer.compoundTypedDataBaseField)
-              ..fileOffset = fileOffset,
+            transformer.getCompoundTypedDataBaseField(
+                ThisExpression(), fileOffset),
             transformer.runtimeBranchOnLayout(offsets),
-            PropertyGet(
-                VariableGet(argument),
-                transformer.compoundTypedDataBaseField.name,
-                transformer.compoundTypedDataBaseField)
-              ..fileOffset = fileOffset,
+            transformer.getCompoundTypedDataBaseField(
+                VariableGet(argument), fileOffset),
             ConstantExpression(IntConstant(0)),
             transformer.runtimeBranchOnLayout(size),
           ]))
@@ -1367,11 +1346,8 @@
         transformer.arrayConstructor,
         Arguments([
           transformer.typedDataBaseOffset(
-              PropertyGet(
-                  ThisExpression(),
-                  transformer.compoundTypedDataBaseField.name,
-                  transformer.compoundTypedDataBaseField)
-                ..fileOffset = fileOffset,
+              transformer.getCompoundTypedDataBaseField(
+                  ThisExpression(), fileOffset),
               transformer.runtimeBranchOnLayout(offsets),
               transformer.runtimeBranchOnLayout(size),
               typeArgument,
@@ -1400,17 +1376,11 @@
       ReturnStatement(StaticInvocation(
           transformer.memCopy,
           Arguments([
-            PropertyGet(
-                ThisExpression(),
-                transformer.compoundTypedDataBaseField.name,
-                transformer.compoundTypedDataBaseField)
-              ..fileOffset = fileOffset,
+            transformer.getCompoundTypedDataBaseField(
+                ThisExpression(), fileOffset),
             transformer.runtimeBranchOnLayout(offsets),
-            PropertyGet(
-                VariableGet(argument),
-                transformer.arrayTypedDataBaseField.name,
-                transformer.arrayTypedDataBaseField)
-              ..fileOffset = fileOffset,
+            transformer.getArrayTypedDataBaseField(
+                VariableGet(argument), fileOffset),
             ConstantExpression(IntConstant(0)),
             transformer.runtimeBranchOnLayout(size),
           ]))
diff --git a/pkg/vm/lib/transformations/ffi_use_sites.dart b/pkg/vm/lib/transformations/ffi_use_sites.dart
index 8f9b4a3..24e4b89 100644
--- a/pkg/vm/lib/transformations/ffi_use_sites.dart
+++ b/pkg/vm/lib/transformations/ffi_use_sites.dart
@@ -327,11 +327,7 @@
         Expression sizeInBytes = _inlineSizeOf(nativeType);
         if (sizeInBytes != null) {
           if (node.arguments.positional.length == 2) {
-            sizeInBytes = MethodInvocation(
-                node.arguments.positional[1],
-                numMultiplication.name,
-                Arguments([sizeInBytes]),
-                numMultiplication);
+            sizeInBytes = multiply(node.arguments.positional[1], sizeInBytes);
           }
           return MethodInvocation(
               node.arguments.positional[0],
@@ -485,11 +481,7 @@
           pointer,
           offsetByMethod.name,
           Arguments([
-            MethodInvocation(
-                node.arguments.positional[1],
-                numMultiplication.name,
-                Arguments([_inlineSizeOf(dartType)]),
-                numMultiplication)
+            multiply(node.arguments.positional[1], _inlineSizeOf(dartType))
           ]),
           offsetByMethod);
     }
@@ -503,10 +495,8 @@
         .firstWhere((c) => c.name == Name("#fromTypedDataBase"));
 
     final typedDataBasePrime = typedDataBaseOffset(
-        PropertyGet(NullCheck(node.arguments.positional[0]),
-            arrayTypedDataBaseField.name, arrayTypedDataBaseField),
-        MethodInvocation(node.arguments.positional[1], numMultiplication.name,
-            Arguments([_inlineSizeOf(dartType)]), numMultiplication),
+        getArrayTypedDataBaseField(NullCheck(node.arguments.positional[0])),
+        multiply(node.arguments.positional[1], _inlineSizeOf(dartType)),
         _inlineSizeOf(dartType),
         dartType,
         node.fileOffset);
@@ -574,26 +564,17 @@
         type: coreTypes.intNonNullableRawType)
       ..fileOffset = node.fileOffset;
     final elementSizeVar = VariableDeclaration("#elementSize",
-        initializer: MethodInvocation(
+        initializer: multiply(
             VariableGet(singleElementSizeVar),
-            numMultiplication.name,
-            Arguments([
-              PropertyGet(
-                  VariableGet(arrayVar),
-                  arrayNestedDimensionsFlattened.name,
-                  arrayNestedDimensionsFlattened)
-            ]),
-            numMultiplication),
+            PropertyGet(
+                VariableGet(arrayVar),
+                arrayNestedDimensionsFlattened.name,
+                arrayNestedDimensionsFlattened)),
         type: coreTypes.intNonNullableRawType)
       ..fileOffset = node.fileOffset;
     final offsetVar = VariableDeclaration("#offset",
-        initializer: MethodInvocation(
-            VariableGet(elementSizeVar),
-            numMultiplication.name,
-            Arguments([
-              VariableGet(indexVar),
-            ]),
-            numMultiplication),
+        initializer:
+            multiply(VariableGet(elementSizeVar), VariableGet(indexVar)),
         type: coreTypes.intNonNullableRawType)
       ..fileOffset = node.fileOffset;
 
@@ -618,8 +599,7 @@
               arrayConstructor,
               Arguments([
                 typedDataBaseOffset(
-                    PropertyGet(VariableGet(arrayVar),
-                        arrayTypedDataBaseField.name, arrayTypedDataBaseField),
+                    getArrayTypedDataBaseField(VariableGet(arrayVar)),
                     VariableGet(offsetVar),
                     VariableGet(elementSizeVar),
                     dartType,
@@ -641,13 +621,11 @@
         StaticInvocation(
             memCopy,
             Arguments([
-              PropertyGet(VariableGet(arrayVar), arrayTypedDataBaseField.name,
-                  arrayTypedDataBaseField)
-                ..fileOffset = node.fileOffset,
+              getArrayTypedDataBaseField(
+                  VariableGet(arrayVar), node.fileOffset),
               VariableGet(offsetVar),
-              PropertyGet(node.arguments.positional[2],
-                  arrayTypedDataBaseField.name, arrayTypedDataBaseField)
-                ..fileOffset = node.fileOffset,
+              getArrayTypedDataBaseField(
+                  node.arguments.positional[2], node.fileOffset),
               ConstantExpression(IntConstant(0)),
               VariableGet(elementSizeVar),
             ]))
@@ -673,13 +651,8 @@
           return MethodInvocation(
               node.receiver,
               offsetByMethod.name,
-              Arguments([
-                MethodInvocation(
-                    node.arguments.positional.single,
-                    numMultiplication.name,
-                    Arguments([inlineSizeOf]),
-                    numMultiplication)
-              ]),
+              Arguments(
+                  [multiply(node.arguments.positional.single, inlineSizeOf)]),
               offsetByMethod);
         }
       }
@@ -711,13 +684,8 @@
           return MethodInvocation(
               node.receiver,
               offsetByMethod.name,
-              Arguments([
-                MethodInvocation(
-                    node.arguments.positional.single,
-                    numMultiplication.name,
-                    Arguments([inlineSizeOf]),
-                    numMultiplication)
-              ]),
+              Arguments(
+                  [multiply(node.arguments.positional.single, inlineSizeOf)]),
               offsetByMethod);
         }
       }
diff --git a/runtime/bin/process.h b/runtime/bin/process.h
index 34fc299..cf141b2 100644
--- a/runtime/bin/process.h
+++ b/runtime/bin/process.h
@@ -170,11 +170,17 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(Process);
 };
 
+typedef void (*sa_handler_t)(int);
+
 class SignalInfo {
  public:
-  SignalInfo(intptr_t fd, intptr_t signal, SignalInfo* next)
+  SignalInfo(intptr_t fd,
+             intptr_t signal,
+             sa_handler_t oldact,
+             SignalInfo* next)
       : fd_(fd),
         signal_(signal),
+        oldact_(oldact),
         // SignalInfo is expected to be created when in a isolate.
         port_(Dart_GetMainPortId()),
         next_(next),
@@ -197,12 +203,14 @@
 
   intptr_t fd() const { return fd_; }
   intptr_t signal() const { return signal_; }
+  sa_handler_t oldact() const { return oldact_; }
   Dart_Port port() const { return port_; }
   SignalInfo* next() const { return next_; }
 
  private:
   intptr_t fd_;
   intptr_t signal_;
+  sa_handler_t oldact_;
   // The port_ is used to identify what isolate the signal-info belongs to.
   Dart_Port port_;
   SignalInfo* next_;
diff --git a/runtime/bin/process_android.cc b/runtime/bin/process_android.cc
index b296299..700de02 100644
--- a/runtime/bin/process_android.cc
+++ b/runtime/bin/process_android.cc
@@ -1009,8 +1009,10 @@
   MutexLocker lock(signal_mutex);
   SignalInfo* handler = signal_handlers;
   bool listen = true;
+  sa_handler_t oldact_handler = nullptr;
   while (handler != NULL) {
     if (handler->signal() == signal) {
+      oldact_handler = handler->oldact();
       listen = false;
       break;
     }
@@ -1023,14 +1025,17 @@
     for (int i = 0; i < kSignalsCount; i++) {
       sigaddset(&act.sa_mask, kSignals[i]);
     }
-    int status = NO_RETRY_EXPECTED(sigaction(signal, &act, NULL));
+    struct sigaction oldact = {};
+    intptr_t status = NO_RETRY_EXPECTED(sigaction(signal, &act, &oldact));
     if (status < 0) {
       close(fds[0]);
       close(fds[1]);
       return -1;
     }
+    oldact_handler = oldact.sa_handler;
   }
-  signal_handlers = new SignalInfo(fds[1], signal, signal_handlers);
+  signal_handlers =
+      new SignalInfo(fds[1], signal, oldact_handler, signal_handlers);
   return fds[0];
 }
 
@@ -1038,7 +1043,9 @@
   ThreadSignalBlocker blocker(kSignalsCount, kSignals);
   MutexLocker lock(signal_mutex);
   SignalInfo* handler = signal_handlers;
-  bool unlisten = true;
+  sa_handler_t oldact_handler = SIG_DFL;
+  bool any_removed = false;
+  bool any_remaining = false;
   while (handler != NULL) {
     bool remove = false;
     if (handler->signal() == signal) {
@@ -1046,10 +1053,12 @@
         if (signal_handlers == handler) {
           signal_handlers = handler->next();
         }
+        oldact_handler = handler->oldact();
         handler->Unlink();
         remove = true;
+        any_removed = true;
       } else {
-        unlisten = false;
+        any_remaining = true;
       }
     }
     SignalInfo* next = handler->next();
@@ -1058,9 +1067,9 @@
     }
     handler = next;
   }
-  if (unlisten) {
+  if (any_removed && !any_remaining) {
     struct sigaction act = {};
-    act.sa_handler = SIG_DFL;
+    act.sa_handler = oldact_handler;
     VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL));
   }
 }
@@ -1069,7 +1078,8 @@
   ThreadSignalBlocker blocker(kSignalsCount, kSignals);
   MutexLocker lock(signal_mutex);
   SignalInfo* handler = signal_handlers;
-  bool unlisten = true;
+  sa_handler_t oldact_handler = SIG_DFL;
+  bool any_remaining = false;
   intptr_t signal = -1;
   while (handler != NULL) {
     bool remove = false;
@@ -1082,7 +1092,7 @@
         remove = true;
         signal = handler->signal();
       } else {
-        unlisten = false;
+        any_remaining = true;
       }
     }
     SignalInfo* next = handler->next();
@@ -1091,9 +1101,9 @@
     }
     handler = next;
   }
-  if (unlisten && (signal != -1)) {
+  if ((signal != -1) && !any_remaining) {
     struct sigaction act = {};
-    act.sa_handler = SIG_DFL;
+    act.sa_handler = oldact_handler;
     VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL));
   }
 }
diff --git a/runtime/bin/process_linux.cc b/runtime/bin/process_linux.cc
index 7c81637..d1897fa 100644
--- a/runtime/bin/process_linux.cc
+++ b/runtime/bin/process_linux.cc
@@ -1003,8 +1003,10 @@
   MutexLocker lock(signal_mutex);
   SignalInfo* handler = signal_handlers;
   bool listen = true;
+  sa_handler_t oldact_handler = nullptr;
   while (handler != NULL) {
     if (handler->signal() == signal) {
+      oldact_handler = handler->oldact();
       listen = false;
       break;
     }
@@ -1017,7 +1019,8 @@
     for (int i = 0; i < kSignalsCount; i++) {
       sigaddset(&act.sa_mask, kSignals[i]);
     }
-    int status = NO_RETRY_EXPECTED(sigaction(signal, &act, NULL));
+    struct sigaction oldact = {};
+    int status = NO_RETRY_EXPECTED(sigaction(signal, &act, &oldact));
     if (status < 0) {
       int err = errno;
       close(fds[0]);
@@ -1025,8 +1028,10 @@
       errno = err;
       return -1;
     }
+    oldact_handler = oldact.sa_handler;
   }
-  signal_handlers = new SignalInfo(fds[1], signal, signal_handlers);
+  signal_handlers =
+      new SignalInfo(fds[1], signal, oldact_handler, signal_handlers);
   return fds[0];
 }
 
@@ -1034,7 +1039,9 @@
   ThreadSignalBlocker blocker(kSignalsCount, kSignals);
   MutexLocker lock(signal_mutex);
   SignalInfo* handler = signal_handlers;
-  bool unlisten = true;
+  sa_handler_t oldact_handler = SIG_DFL;
+  bool any_removed = false;
+  bool any_remaining = false;
   while (handler != NULL) {
     bool remove = false;
     if (handler->signal() == signal) {
@@ -1044,8 +1051,10 @@
         }
         handler->Unlink();
         remove = true;
+        oldact_handler = handler->oldact();
+        any_removed = true;
       } else {
-        unlisten = false;
+        any_remaining = true;
       }
     }
     SignalInfo* next = handler->next();
@@ -1054,9 +1063,9 @@
     }
     handler = next;
   }
-  if (unlisten) {
+  if (any_removed && !any_remaining) {
     struct sigaction act = {};
-    act.sa_handler = SIG_DFL;
+    act.sa_handler = oldact_handler;
     VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL));
   }
 }
@@ -1065,7 +1074,8 @@
   ThreadSignalBlocker blocker(kSignalsCount, kSignals);
   MutexLocker lock(signal_mutex);
   SignalInfo* handler = signal_handlers;
-  bool unlisten = true;
+  sa_handler_t oldact_handler = SIG_DFL;
+  bool any_remaining = false;
   intptr_t signal = -1;
   while (handler != NULL) {
     bool remove = false;
@@ -1078,7 +1088,7 @@
         remove = true;
         signal = handler->signal();
       } else {
-        unlisten = false;
+        any_remaining = true;
       }
     }
     SignalInfo* next = handler->next();
@@ -1087,9 +1097,9 @@
     }
     handler = next;
   }
-  if (unlisten && (signal != -1)) {
+  if ((signal != -1) && !any_remaining) {
     struct sigaction act = {};
-    act.sa_handler = SIG_DFL;
+    act.sa_handler = oldact_handler;
     VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL));
   }
 }
diff --git a/runtime/bin/process_macos.cc b/runtime/bin/process_macos.cc
index 624ea8a..78a84ba 100644
--- a/runtime/bin/process_macos.cc
+++ b/runtime/bin/process_macos.cc
@@ -1037,8 +1037,10 @@
   MutexLocker lock(signal_mutex);
   SignalInfo* handler = signal_handlers;
   bool listen = true;
+  sa_handler_t oldact_handler = nullptr;
   while (handler != NULL) {
     if (handler->signal() == signal) {
+      oldact_handler = handler->oldact();
       listen = false;
       break;
     }
@@ -1051,14 +1053,17 @@
     for (int i = 0; i < kSignalsCount; i++) {
       sigaddset(&act.sa_mask, kSignals[i]);
     }
-    intptr_t status = NO_RETRY_EXPECTED(sigaction(signal, &act, NULL));
+    struct sigaction oldact = {};
+    intptr_t status = NO_RETRY_EXPECTED(sigaction(signal, &act, &oldact));
     if (status < 0) {
       close(fds[0]);
       close(fds[1]);
       return -1;
     }
+    oldact_handler = oldact.sa_handler;
   }
-  signal_handlers = new SignalInfo(fds[1], signal, signal_handlers);
+  signal_handlers =
+      new SignalInfo(fds[1], signal, oldact_handler, signal_handlers);
   return fds[0];
 }
 
@@ -1070,7 +1075,9 @@
   ThreadSignalBlocker blocker(kSignalsCount, kSignals);
   MutexLocker lock(signal_mutex);
   SignalInfo* handler = signal_handlers;
-  bool unlisten = true;
+  sa_handler_t oldact_handler = SIG_DFL;
+  bool any_removed = false;
+  bool any_remaining = false;
   while (handler != NULL) {
     bool remove = false;
     if (handler->signal() == signal) {
@@ -1080,8 +1087,10 @@
         }
         handler->Unlink();
         remove = true;
+        oldact_handler = handler->oldact();
+        any_removed = true;
       } else {
-        unlisten = false;
+        any_remaining = true;
       }
     }
     SignalInfo* next = handler->next();
@@ -1090,9 +1099,9 @@
     }
     handler = next;
   }
-  if (unlisten) {
+  if (any_removed && !any_remaining) {
     struct sigaction act = {};
-    act.sa_handler = SIG_DFL;
+    act.sa_handler = oldact_handler;
     VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL));
   }
 }
@@ -1101,7 +1110,8 @@
   ThreadSignalBlocker blocker(kSignalsCount, kSignals);
   MutexLocker lock(signal_mutex);
   SignalInfo* handler = signal_handlers;
-  bool unlisten = true;
+  sa_handler_t oldact_handler = SIG_DFL;
+  bool any_remaining = false;
   intptr_t signal = -1;
   while (handler != NULL) {
     bool remove = false;
@@ -1114,7 +1124,7 @@
         remove = true;
         signal = handler->signal();
       } else {
-        unlisten = false;
+        any_remaining = true;
       }
     }
     SignalInfo* next = handler->next();
@@ -1123,9 +1133,9 @@
     }
     handler = next;
   }
-  if (unlisten && (signal != -1)) {
+  if ((signal != -1) && !any_remaining) {
     struct sigaction act = {};
-    act.sa_handler = SIG_DFL;
+    act.sa_handler = oldact_handler;
     VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL));
   }
 }
diff --git a/runtime/bin/process_win.cc b/runtime/bin/process_win.cc
index 8edd8dd..b3bc9a9 100644
--- a/runtime/bin/process_win.cc
+++ b/runtime/bin/process_win.cc
@@ -1032,7 +1032,8 @@
       return -1;
     }
   }
-  signal_handlers = new SignalInfo(write_fd, signal, signal_handlers);
+  signal_handlers =
+      new SignalInfo(write_fd, signal, /*oldact=*/nullptr, signal_handlers);
   return reinterpret_cast<intptr_t>(new FileHandle(fds[kReadHandle]));
 }
 
diff --git a/tools/VERSION b/tools/VERSION
index 99a1532..497b456 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 93
+PRERELEASE 94
 PRERELEASE_PATCH 0
\ No newline at end of file