mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 17:18:04 +00:00
[io] Fix a bug where Process.stdin.add exceptions could not be caught
Change-Id: I2383a74bfa6950ab8f8934087fb68218f06dd681 Bug:https://github.com/dart-lang/sdk/issues/48501 Tested: Unit test CoreLibraryReviewExempt: dart:io only Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/351380 Reviewed-by: Alexander Aprelev <aam@google.com> Commit-Queue: Brian Quinlan <bquinlan@google.com>
This commit is contained in:
parent
6ca01d0854
commit
9967075787
|
@ -282,6 +282,11 @@ base class _ProcessImpl extends _ProcessImplNativeWrapper implements _Process {
|
|||
if (_modeHasStdio(_mode)) {
|
||||
// stdin going to process.
|
||||
_stdin = new _StdSink(new _Socket._writePipe().._owner = this);
|
||||
// Ignore errors if the `Process.stdin.done` future is not consumed.
|
||||
// Developers catch errors writing to `Process.stdin` by consuming
|
||||
// `Process.stdin.done` or calling `Process.stdin.flush()`.
|
||||
_stdin!.done.ignore();
|
||||
|
||||
// stdout coming from process.
|
||||
_stdout = new _StdStream(new _Socket._readPipe().._owner = this);
|
||||
// stderr coming from process.
|
||||
|
|
|
@ -492,6 +492,29 @@ abstract interface class Process {
|
|||
Stream<List<int>> get stderr;
|
||||
|
||||
/// The standard input stream of the process as an [IOSink].
|
||||
///
|
||||
/// `stdin` is implemented as a pipe between the parent process and the
|
||||
/// spawned subprocess.
|
||||
///
|
||||
/// Data added to the [IOSink] (E.g. `Process.stdin.writeln('Hello!')`) is
|
||||
/// written to to the pipe asynchronously.
|
||||
///
|
||||
/// Errors writing the data (e.g. due to the subprocess exiting) can be
|
||||
/// caught by awaiting `Process.stdin.flush()`. For example:
|
||||
///
|
||||
/// ```dart
|
||||
/// import 'dart:io';
|
||||
///
|
||||
/// main() async {
|
||||
/// final process = await Process.start('false', const <String>[]);
|
||||
/// process.stdin.writeln('Hello World\n'); // May already have exited.
|
||||
/// try {
|
||||
/// await process.stdin.flush();
|
||||
/// } catch (e) {
|
||||
/// print(e);
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
IOSink get stdin;
|
||||
|
||||
/// The process id of the process.
|
||||
|
|
54
tests/standalone/io/process_stdin_broken_pipe_test.dart
Normal file
54
tests/standalone/io/process_stdin_broken_pipe_test.dart
Normal file
|
@ -0,0 +1,54 @@
|
|||
// Copyright (c) 2024, 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.
|
||||
//
|
||||
// Verify that failing to write to `Process.stdin` results in an exception
|
||||
// being thrown by `process.stdin.flush()` and `process.stdin.done`.
|
||||
//
|
||||
// See https://github.com/dart-lang/sdk/issues/48501
|
||||
//
|
||||
// VMOptions=
|
||||
// VMOptions=--short_socket_read
|
||||
// VMOptions=--short_socket_write
|
||||
// VMOptions=--short_socket_read --short_socket_write
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
|
||||
import "process_test_util.dart";
|
||||
|
||||
Future test(Process process) async {}
|
||||
|
||||
void main() async {
|
||||
if (!Platform.isLinux && !Platform.isMacOS) {
|
||||
print('test not supported on ${Platform.operatingSystem}');
|
||||
return;
|
||||
}
|
||||
|
||||
final process = await Process.start('false', const <String>[]);
|
||||
try {
|
||||
for (var i = 0; i < 20; ++i) {
|
||||
// Ensure that the pipe is broken while we are writing.
|
||||
process.stdin.add([1, 2, 3]);
|
||||
await Future.delayed(const Duration(milliseconds: 50));
|
||||
}
|
||||
|
||||
try {
|
||||
await process.stdin.flush();
|
||||
Expect.fail('await process.stdin.flush(): expected exception');
|
||||
} on SocketException catch (e) {
|
||||
Expect.equals(32, e.osError!.errorCode); // Broken pipe
|
||||
}
|
||||
|
||||
try {
|
||||
await process.stdin.done;
|
||||
Expect.fail('await process.stdin.done: expected exception');
|
||||
} on SocketException catch (e) {
|
||||
Expect.equals(32, e.osError!.errorCode); // Broken pipe
|
||||
}
|
||||
} finally {
|
||||
process.kill();
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue