Files
sdk/runtime/bin/stdio_patch.dart
T
Zachary Anderson 8c9c54d833 [dart:io] Don't close stdin with a socket finalizer
If an Isolate touches the 'stdio' getter, a _NativeSocket with
attached finalizer is created for it. Previously, when such an
Isolate exited, the finalizer would close the underlying
file descriptor. This CL changes the finalizer for stdin such
that the native objects will be cleaned up, but the underlying
file descriptor will not be closed. The underlying file
descriptor will now only be closed if the stdin stream
subscription is explicitly canceled.

Accessing the stdin getter after the stream is explicitly
canceled will result in a FileSystemException.

See also: https://github.com/dart-lang/test/issues/583

fixes #29229

R=rmacnak@google.com

Review-Url: https://codereview.chromium.org/2791423002 .
2017-04-04 13:57:42 -07:00

156 lines
4.1 KiB
Dart

// Copyright (c) 2013, 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.
@patch
class _StdIOUtils {
@patch
static Stdin _getStdioInputStream() {
switch (_getStdioHandleType(0)) {
case _STDIO_HANDLE_TYPE_TERMINAL:
case _STDIO_HANDLE_TYPE_PIPE:
case _STDIO_HANDLE_TYPE_SOCKET:
return new Stdin._(new _Socket._readPipe(0));
case _STDIO_HANDLE_TYPE_FILE:
return new Stdin._(new _FileStream.forStdin());
default:
throw new FileSystemException(
"Couldn't determine file type of stdin (fd 0)");
}
}
@patch
static _getStdioOutputStream(int fd) {
assert(fd == 1 || fd == 2);
switch (_getStdioHandleType(fd)) {
case _STDIO_HANDLE_TYPE_TERMINAL:
case _STDIO_HANDLE_TYPE_PIPE:
case _STDIO_HANDLE_TYPE_SOCKET:
case _STDIO_HANDLE_TYPE_FILE:
return new Stdout._(new IOSink(new _StdConsumer(fd)), fd);
default:
throw new FileSystemException(
"Couldn't determine file type of stdio handle (fd $fd)");
}
}
@patch
static int _socketType(Socket socket) {
if (socket is _Socket) return _nativeSocketType(socket._nativeSocket);
return null;
}
static int _nativeSocketType(_NativeSocket nativeSocket) {
var result = _getSocketType(nativeSocket);
if (result is OSError) {
throw new FileSystemException("Error retrieving socket type", "", result);
}
return result;
}
@patch
static _getStdioHandleType(int fd) native "File_GetStdioHandleType";
}
@patch
class Stdin {
@patch
int readByteSync() {
var result = _readByte();
if (result is OSError) {
throw new StdinException("Error reading byte from stdin", result);
}
return result;
}
@patch
bool get echoMode {
var result = _echoMode();
if (result is OSError) {
throw new StdinException("Error getting terminal echo mode", result);
}
return result;
}
@patch
void set echoMode(bool enabled) {
var result = _setEchoMode(enabled);
if (result is OSError) {
throw new StdinException("Error setting terminal echo mode", result);
}
}
@patch
bool get lineMode {
var result = _lineMode();
if (result is OSError) {
throw new StdinException("Error getting terminal line mode", result);
}
return result;
}
@patch
void set lineMode(bool enabled) {
var result = _setLineMode(enabled);
if (result is OSError) {
throw new StdinException("Error setting terminal line mode", result);
}
}
@patch bool get supportsAnsiEscapes {
var result = _supportsAnsiEscapes();
if (result is OSError) {
throw new StdinException("Error determining ANSI support", result);
}
return result;
}
static _echoMode() native "Stdin_GetEchoMode";
static _setEchoMode(bool enabled) native "Stdin_SetEchoMode";
static _lineMode() native "Stdin_GetLineMode";
static _setLineMode(bool enabled) native "Stdin_SetLineMode";
static _readByte() native "Stdin_ReadByte";
static _supportsAnsiEscapes() native "Stdin_AnsiSupported";
}
@patch
class Stdout {
@patch
bool _hasTerminal(int fd) {
try {
_terminalSize(fd);
return true;
} catch (_) {
return false;
}
}
@patch
int _terminalColumns(int fd) => _terminalSize(fd)[0];
@patch
int _terminalLines(int fd) => _terminalSize(fd)[1];
static List _terminalSize(int fd) {
var size = _getTerminalSize(fd);
if (size is! List) {
throw new StdoutException("Could not get terminal size", size);
}
return size;
}
static _getTerminalSize(int fd) native "Stdout_GetTerminalSize";
@patch static bool _supportsAnsiEscapes(int fd) {
var result = _getAnsiSupported(fd);
if (result is! bool) {
throw new StdoutException("Error determining ANSI support", result);
}
return result;
}
static _getAnsiSupported(int fd) native "Stdout_AnsiSupported";
}
_getStdioHandle(_NativeSocket socket, int num) native "Socket_GetStdioHandle";
_getSocketType(_NativeSocket nativeSocket) native "Socket_GetType";