Repository: flutter
Issue: "flutter pub get" does not terminate when killed
Labels: tool,P2,team-tool,triaged-tool

This came up in https://github.com/Dart-Code/Dart-Code/issues/2612. If you run `flutter pub get` and try to kill it programatically (similar to how Dart-Code would if you clicked the Cancel button on the dialog), the process doesn't terminate.

To repro, you can use this script which creates a `pubspec.yaml` with an invalid package name, which puts Flutter into an endless loop of retries (which is discussed in https://github.com/dart-lang/pub/issues/2242), and then tries to kill it - however it does not stop.

I repro'd this using latest Flutter master today.

```dart
import 'dart:io';

import 'package:path/path.dart' as path;

Future<void> main() async {
  // Create a temp project
  final projectFolder = Directory(path.join(Directory.systemTemp.path, 'flutter_pub_test'))
        ..createSync(recursive: true);

  // Write a pubspec with a bad package name
  File(path.join(projectFolder.path, 'pubspec.yaml'))
    ..writeAsStringSync('name: sample\n'
        "environment:\n  sdk: '>=2.10.0 <3.0.0'\n"
        'dependencies:\n  not_a_real_package:');

  // Run "flutter pub get" and print any stdout/stderr output
  final proc = await Process.start(
      'flutter', ['pub', 'get'],
      workingDirectory: projectFolder.path,
  );
  proc.stdout.listen((s) => print(String.fromCharCodes(s)));
  proc.stderr.listen((s) => print(String.fromCharCodes(s)));

  // Kill the process and wait for it to end
  await Future.delayed(Duration(seconds: 2));
  print('Killing process!');
  proc.kill();

  print('Waiting for exit!');
  await proc.exitCode;
}
```

Output:

```
Running "flutter pub get" in flutter_pub_test...

Because sample depends on not_a_real_package any which doesn't exist (could not find package not_a_real_package at https://pub.dartlang.org), version solving failed.

pub get failed (server unavailable) -- attempting retry 1 in 1 second...
Killing process!
Waiting for exit!

Because sample depends on not_a_real_package any which doesn't exist (could not find package not_a_real_package at https://pub.dartlang.org), version solving failed.

pub get failed (server unavailable) -- attempting retry 2 in 2 seconds...


Because sample depends on not_a_real_package any which doesn't exist (could not find package not_a_real_package at https://pub.dartlang.org), version solving failed.

pub get failed (server unavailable) -- attempting retry 3 in 4 seconds...

Because sample depends on not_a_real_package any which doesn't exist (could not find package not_a_real_package at https://pub.dartlang.org), version solving failed.

pub get failed (server unavailable) -- attempting retry 4 in 8 seconds...

// etc.
```

This results in orphaned processes being left around forever if the user ever saves pubspec with an invalid package name. I thought it might have been related to https://github.com/dart-lang/sdk/issues/42092, however that seems to have been included in this version of Flutter but it's still not fixed.

(it's very possible this is a similar issue to we have elsewhere, where sending kill signals to a shell-executed process is unreliable.. we get around this in may places by emitting some JSON with the pid and adding that to the list of things to terminate - however `pub get` doesn't have a machine mode to add that too).