mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 04:57:43 +00:00
[ DDS ] Update DDS launch sites to assume DDS process closes stderr
Removes risk of DDS connection information being split across two stream events, causing JSON decoding to fail. Also updates DDS to close stderr, even in the error case. TEST=Existing service and dartdev tests Change-Id: I5cceab899aac1fa63bd7578dd658b34096722bd3 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/371000 Reviewed-by: Derek Xu <derekx@google.com>
This commit is contained in:
parent
b640dffb0a
commit
cf9623f3d9
|
@ -46,12 +46,17 @@ class DDSRunner {
|
||||||
],
|
],
|
||||||
mode: ProcessStartMode.detachedWithStdio,
|
mode: ProcessStartMode.detachedWithStdio,
|
||||||
);
|
);
|
||||||
final completer = Completer<void>();
|
|
||||||
|
// NOTE: update pkg/dartdev/lib/src/commands/run.dart if this message
|
||||||
|
// is changed to ensure consistency.
|
||||||
const devToolsMessagePrefix =
|
const devToolsMessagePrefix =
|
||||||
'The Dart DevTools debugger and profiler is available at:';
|
'The Dart DevTools debugger and profiler is available at:';
|
||||||
if (debugDds) {
|
if (debugDds) {
|
||||||
late final StreamSubscription stdoutSub;
|
late final StreamSubscription stdoutSub;
|
||||||
stdoutSub = process.stdout.transform(utf8.decoder).listen((event) {
|
stdoutSub = process.stdout
|
||||||
|
.transform(utf8.decoder)
|
||||||
|
.transform(const LineSplitter())
|
||||||
|
.listen((event) {
|
||||||
if (event.startsWith(devToolsMessagePrefix)) {
|
if (event.startsWith(devToolsMessagePrefix)) {
|
||||||
final ddsDebuggingUri = event.split(' ').last;
|
final ddsDebuggingUri = event.split(' ').last;
|
||||||
print(
|
print(
|
||||||
|
@ -61,21 +66,27 @@ class DDSRunner {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
late final StreamSubscription stderrSub;
|
|
||||||
stderrSub = process.stderr.transform(utf8.decoder).listen((event) {
|
// DDS will close stderr once it's finished launching.
|
||||||
final result = json.decode(event) as Map<String, dynamic>;
|
final launchResult = await process.stderr.transform(utf8.decoder).join();
|
||||||
final state = result['state'];
|
|
||||||
if (state == 'started') {
|
void printError(String details) => stderr.writeln(
|
||||||
if (result.containsKey('devToolsUri')) {
|
'Could not start the VM service:\n$details',
|
||||||
final devToolsUri = result['devToolsUri'];
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
final result = json.decode(launchResult);
|
||||||
|
if (result
|
||||||
|
case {
|
||||||
|
'state': 'started',
|
||||||
|
'ddsUri': final String ddsUriStr,
|
||||||
|
}) {
|
||||||
|
ddsUri = Uri.parse(ddsUriStr);
|
||||||
|
if (result case {'devToolsUri': String devToolsUri}) {
|
||||||
print('$devToolsMessagePrefix $devToolsUri');
|
print('$devToolsMessagePrefix $devToolsUri');
|
||||||
}
|
}
|
||||||
ddsUri = Uri.parse(result['ddsUri']);
|
|
||||||
stderrSub.cancel();
|
|
||||||
completer.complete();
|
|
||||||
} else {
|
} else {
|
||||||
stderrSub.cancel();
|
final error = result['error'] ?? result;
|
||||||
final error = result['error'] ?? event;
|
|
||||||
final stacktrace = result['stacktrace'] ?? '';
|
final stacktrace = result['stacktrace'] ?? '';
|
||||||
String message = 'Could not start the VM service: ';
|
String message = 'Could not start the VM service: ';
|
||||||
if (error.contains('Failed to create server socket')) {
|
if (error.contains('Failed to create server socket')) {
|
||||||
|
@ -83,15 +94,15 @@ class DDSRunner {
|
||||||
} else {
|
} else {
|
||||||
message += '$error\n$stacktrace\n';
|
message += '$error\n$stacktrace\n';
|
||||||
}
|
}
|
||||||
completer.completeError(message);
|
printError(message);
|
||||||
}
|
|
||||||
});
|
|
||||||
try {
|
|
||||||
await completer.future;
|
|
||||||
return true;
|
|
||||||
} catch (e) {
|
|
||||||
stderr.write(e);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
} catch (_) {
|
||||||
|
// Malformed JSON was likely encountered, so output the entirety of
|
||||||
|
// stderr in the error message.
|
||||||
|
printError(launchResult);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,6 +131,10 @@ ${argParser.usage}
|
||||||
stderr.close();
|
stderr.close();
|
||||||
} catch (e, st) {
|
} catch (e, st) {
|
||||||
writeErrorResponse(e, st);
|
writeErrorResponse(e, st);
|
||||||
|
} finally {
|
||||||
|
// Always close stderr to notify tooling that DDS has finished writing
|
||||||
|
// launch details.
|
||||||
|
await stderr.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,12 +114,20 @@ class _DebuggingSession {
|
||||||
],
|
],
|
||||||
mode: ProcessStartMode.detachedWithStdio,
|
mode: ProcessStartMode.detachedWithStdio,
|
||||||
);
|
);
|
||||||
final completer = Completer<void>();
|
|
||||||
late StreamSubscription<String> stderrSub;
|
// DDS will close stderr once it's finished launching.
|
||||||
stderrSub = _process!.stderr.transform(utf8.decoder).listen((event) {
|
final launchResult = await _process!.stderr.transform(utf8.decoder).join();
|
||||||
final result = json.decode(event) as Map<String, dynamic>;
|
|
||||||
final state = result['state'];
|
void printError(String details) => stderr.writeln(
|
||||||
if (state == 'started') {
|
'Could not start the VM service:\n$details',
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
final result = json.decode(launchResult);
|
||||||
|
if (result
|
||||||
|
case {
|
||||||
|
'state': 'started',
|
||||||
|
}) {
|
||||||
if (result case {'devToolsUri': String devToolsUri}) {
|
if (result case {'devToolsUri': String devToolsUri}) {
|
||||||
// NOTE: update pkg/dartdev/lib/src/commands/run.dart if this message
|
// NOTE: update pkg/dartdev/lib/src/commands/run.dart if this message
|
||||||
// is changed to ensure consistency.
|
// is changed to ensure consistency.
|
||||||
|
@ -135,21 +143,17 @@ class _DebuggingSession {
|
||||||
} when _printDtd) {
|
} when _printDtd) {
|
||||||
print('The Dart Tooling Daemon (DTD) is available at: $dtdUri');
|
print('The Dart Tooling Daemon (DTD) is available at: $dtdUri');
|
||||||
}
|
}
|
||||||
stderrSub.cancel();
|
|
||||||
completer.complete();
|
|
||||||
} else {
|
} else {
|
||||||
final error = result['error'] ?? event;
|
printError(result['error'] ?? result);
|
||||||
stderrSub.cancel();
|
|
||||||
completer.completeError('Could not start the VM service:\n$error\n');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
try {
|
|
||||||
await completer.future;
|
|
||||||
return true;
|
|
||||||
} catch (e) {
|
|
||||||
stderr.write(e);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
} catch (_) {
|
||||||
|
// Malformed JSON was likely encountered, so output the entirety of
|
||||||
|
// stderr in the error message.
|
||||||
|
printError(launchResult);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void shutdown() => _process!.kill();
|
void shutdown() => _process!.kill();
|
||||||
|
|
Loading…
Reference in a new issue