[dds/dap] Prevent exceptions writing to stdout.nonBlocking from going unhandled

Because we use `nonBlocking`, the stream closing with unflushed data can result in an unhandled exception. Since we're never interested in errors writing to the stream (there's nothing we can do if the output stream is closed, and it happens at the end of every session), we just discard the error.

Fixes https://github.com/dart-lang/sdk/issues/61193
Fixes https://github.com/dart-lang/sdk/issues/55685
Fixes https://github.com/dart-lang/sdk/issues/55313

Change-Id: I6e0a332708cd6e8eb3ae8bd60d45c9e117d897a6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/452440
Reviewed-by: Ben Konyi <bkonyi@google.com>
Reviewed-by: Helin Shiah <helinx@google.com>
Commit-Queue: Helin Shiah <helinx@google.com>
This commit is contained in:
Danny Tuppeny
2025-10-13 09:19:06 -07:00
committed by Commit Queue
parent 278ea48c7e
commit da8ed2208e
3 changed files with 9 additions and 10 deletions
@@ -67,6 +67,12 @@ class DebugAdapterCommand extends DartdevCommand {
final args = argResults!;
final ipv6 = args.flag(argIpv6);
// Because we use stdout.nonBlocking, exceptions may go unhandled if the
// stream closes while data is being flushed ("The pipe is being closed").
// To prevent this, install an error handler that ignores any errors writing
// to the stream.
stdout.nonBlocking.done.catchError((e) {});
final server = DapServer(
stdin,
stdout.nonBlocking,
@@ -13,12 +13,7 @@ main() {
group('debug mode', () {
late DapTestSession dap;
setUp(() async {
dap = await DapTestSession.setUp(
/// This boolean is temporarily set to `true` to aid debugging
/// https://github.com/dart-lang/sdk/issues/55313 and will be reverted
/// soon.
forceVerboseLogging: true,
);
dap = await DapTestSession.setUp();
});
tearDown(() => dap.tearDown());
@@ -12,9 +12,7 @@ main() {
group('debug mode', () {
late DapTestSession dap;
setUp(() async {
// Temporarily enable verbose logging to help track down
// https://github.com/dart-lang/sdk/issues/55685
dap = await DapTestSession.setUp(forceVerboseLogging: true);
dap = await DapTestSession.setUp();
});
tearDown(() => dap.tearDown());
@@ -57,7 +55,7 @@ main() {
// Run the app and expect it to complete (it should not pause).
final outputEvents = await client.collectOutput(file: testFile);
// Expect error info printed to stderr.
// Expect error info sent to stdout via `print()`.
final output = outputEvents
.where((e) => e.category == 'stdout')
.map((e) => e.output)