Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
93a5b7d4
Commit
93a5b7d4
authored
Jan 25, 2020
by
Zachary Anderson
Committed by
Flutter GitHub Bot
Jan 25, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[flutter_tool] Don't crash on a failure to write to std{out,err} (#49380)
parent
bcfc293c
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
123 additions
and
43 deletions
+123
-43
runner.dart
packages/flutter_tools/lib/runner.dart
+6
-5
io.dart
packages/flutter_tools/lib/src/base/io.dart
+16
-0
logger.dart
packages/flutter_tools/lib/src/base/logger.dart
+43
-26
daemon.dart
packages/flutter_tools/lib/src/commands/daemon.dart
+10
-4
shell_completion.dart
...ages/flutter_tools/lib/src/commands/shell_completion.dart
+2
-1
logger_test.dart
...es/flutter_tools/test/general.shard/base/logger_test.dart
+46
-7
No files found.
packages/flutter_tools/lib/runner.dart
View file @
93a5b7d4
...
...
@@ -112,12 +112,12 @@ Future<int> _handleToolError(
}
}
else
{
// We've crashed; emit a log report.
s
tderr
.
writeln
(
);
s
afeStdioWrite
(
stderr
,
'
\n
'
);
if
(!
reportCrashes
)
{
// Print the stack trace on the bots - don't write a crash report.
s
tderr
.
writeln
(
'
$error
'
);
s
tderr
.
writeln
(
stackTrace
.
toString
()
);
s
afeStdioWrite
(
stderr
,
'
$error
\n
'
);
s
afeStdioWrite
(
stderr
,
'
$stackTrace
\n
'
);
return
_exit
(
1
);
}
...
...
@@ -138,9 +138,10 @@ Future<int> _handleToolError(
return
_exit
(
1
);
}
catch
(
error
)
{
stderr
.
writeln
(
safeStdioWrite
(
stderr
,
'Unable to generate crash report due to secondary error:
$error
\n
'
'please let us know at https://github.com/flutter/flutter/issues.
'
,
'please let us know at https://github.com/flutter/flutter/issues.
\n
'
,
);
// Any exception throw here (including one thrown by `_exit()`) will
// get caught by our zone's `onError` handler. In order to avoid an
...
...
packages/flutter_tools/lib/src/base/io.dart
View file @
93a5b7d4
...
...
@@ -253,6 +253,22 @@ Stream<List<int>> get stdin => globals.stdio.stdin;
io
.
IOSink
get
stderr
=>
globals
.
stdio
.
stderr
;
bool
get
stdinHasTerminal
=>
globals
.
stdio
.
stdinHasTerminal
;
/// Writes [message] to [sink], falling back on [fallback] if the write
/// throws any exception. The default fallback calls [print] on [message].
void
safeStdioWrite
(
io
.
IOSink
sink
,
String
message
,
{
void
Function
(
String
,
dynamic
,
StackTrace
)
fallback
,
})
{
try
{
sink
.
write
(
message
);
}
catch
(
err
,
stack
)
{
if
(
fallback
==
null
)
{
print
(
message
);
}
else
{
fallback
(
message
,
err
,
stack
);
}
}
}
// TODO(zra): Move pid and writePidFile into `ProcessInfo`.
void
writePidFile
(
String
pidFile
)
{
if
(
pidFile
!=
null
)
{
...
...
packages/flutter_tools/lib/src/base/logger.dart
View file @
93a5b7d4
...
...
@@ -229,9 +229,9 @@ class StdoutLogger extends Logger {
message
=
_terminal
.
bolden
(
message
);
}
message
=
_terminal
.
color
(
message
,
color
??
TerminalColor
.
red
);
_stdio
.
stderr
.
writeln
(
message
);
writeToStdErr
(
'
$message
\n
'
);
if
(
stackTrace
!=
null
)
{
_stdio
.
stderr
.
writeln
(
stackTrace
.
toString
()
);
writeToStdErr
(
'
$stackTrace
\n
'
);
}
_status
?.
resume
();
}
...
...
@@ -269,7 +269,12 @@ class StdoutLogger extends Logger {
@protected
void
writeToStdOut
(
String
message
)
{
_stdio
.
stdout
.
write
(
message
);
safeStdioWrite
(
_stdio
.
stdout
,
message
);
}
@protected
void
writeToStdErr
(
String
message
)
{
safeStdioWrite
(
_stdio
.
stderr
,
message
);
}
@override
...
...
@@ -355,10 +360,10 @@ class WindowsStdoutLogger extends StdoutLogger {
@override
void
writeToStdOut
(
String
message
)
{
// TODO(jcollins-g): wrong abstraction layer for this, move to [Stdio].
_stdio
.
stdout
.
write
(
message
.
replaceAll
(
'✗'
,
'X'
)
.
replaceAll
(
'✓'
,
'√'
)
);
final
String
windowsMessage
=
message
.
replaceAll
(
'✗'
,
'X'
)
.
replaceAll
(
'✓'
,
'√'
);
safeStdioWrite
(
_stdio
.
stdout
,
windowsMessage
);
}
}
...
...
@@ -789,9 +794,13 @@ class SummaryStatus extends Status {
super
.
start
();
}
void
_writeToStdOut
(
String
message
)
{
safeStdioWrite
(
_stdio
.
stdout
,
message
);
}
void
_printMessage
()
{
assert
(!
_messageShowingOnCurrentLine
);
_
stdio
.
stdout
.
write
(
'
${message.padRight(padding)}
'
);
_
writeToStdOut
(
'
${message.padRight(padding)}
'
);
_messageShowingOnCurrentLine
=
true
;
}
...
...
@@ -802,14 +811,14 @@ class SummaryStatus extends Status {
}
super
.
stop
();
writeSummaryInformation
();
_
stdio
.
stdout
.
write
(
'
\n
'
);
_
writeToStdOut
(
'
\n
'
);
}
@override
void
cancel
()
{
super
.
cancel
();
if
(
_messageShowingOnCurrentLine
)
{
_
stdio
.
stdout
.
write
(
'
\n
'
);
_
writeToStdOut
(
'
\n
'
);
}
}
...
...
@@ -822,16 +831,16 @@ class SummaryStatus extends Status {
/// Examples: ` 0.5s`, ` 150ms`, ` 1,600ms`, ` 3.1s (!)`
void
writeSummaryInformation
()
{
assert
(
_messageShowingOnCurrentLine
);
_
stdio
.
stdout
.
write
(
elapsedTime
.
padLeft
(
_kTimePadding
));
_
writeToStdOut
(
elapsedTime
.
padLeft
(
_kTimePadding
));
if
(
seemsSlow
)
{
_
stdio
.
stdout
.
write
(
' (!)'
);
_
writeToStdOut
(
' (!)'
);
}
}
@override
void
pause
()
{
super
.
pause
();
_
stdio
.
stdout
.
write
(
'
\n
'
);
_
writeToStdOut
(
'
\n
'
);
_messageShowingOnCurrentLine
=
false
;
}
}
...
...
@@ -894,8 +903,12 @@ class AnsiSpinner extends Status {
_startSpinner
();
}
void
_writeToStdOut
(
String
message
)
{
safeStdioWrite
(
_stdio
.
stdout
,
message
);
}
void
_startSpinner
()
{
_
stdio
.
stdout
.
write
(
_clear
);
// for _callback to backspace over
_
writeToStdOut
(
_clear
);
// for _callback to backspace over
timer
=
Timer
.
periodic
(
const
Duration
(
milliseconds:
100
),
_callback
);
_callback
(
timer
);
}
...
...
@@ -904,21 +917,21 @@ class AnsiSpinner extends Status {
assert
(
this
.
timer
==
timer
);
assert
(
timer
!=
null
);
assert
(
timer
.
isActive
);
_
stdio
.
stdout
.
write
(
_backspace
);
_
writeToStdOut
(
_backspace
);
ticks
+=
1
;
if
(
seemsSlow
)
{
if
(!
timedOut
)
{
timedOut
=
true
;
_
stdio
.
stdout
.
write
(
'
$_clear
\n
'
);
_
writeToStdOut
(
'
$_clear
\n
'
);
}
if
(
slowWarningCallback
!=
null
)
{
_slowWarning
=
slowWarningCallback
();
}
else
{
_slowWarning
=
_defaultSlowWarning
;
}
_
stdio
.
stdout
.
write
(
_slowWarning
);
_
writeToStdOut
(
_slowWarning
);
}
_
stdio
.
stdout
.
write
(
'
${_clearChar * spinnerIndent}$_currentAnimationFrame
'
);
_
writeToStdOut
(
'
${_clearChar * spinnerIndent}$_currentAnimationFrame
'
);
}
@override
...
...
@@ -932,7 +945,7 @@ class AnsiSpinner extends Status {
}
void
_clearSpinner
()
{
_
stdio
.
stdout
.
write
(
'
$_backspace$_clear$_backspace
'
);
_
writeToStdOut
(
'
$_backspace$_clear$_backspace
'
);
}
@override
...
...
@@ -1002,20 +1015,20 @@ class AnsiStatus extends AnsiSpinner {
void
_startStatus
()
{
final
String
line
=
'
${message.padRight(padding)}$_margin
'
;
_totalMessageLength
=
line
.
length
;
_
stdio
.
stdout
.
write
(
line
);
_
writeToStdOut
(
line
);
}
@override
void
stop
()
{
super
.
stop
();
writeSummaryInformation
();
_
stdio
.
stdout
.
write
(
'
\n
'
);
_
writeToStdOut
(
'
\n
'
);
}
@override
void
cancel
()
{
super
.
cancel
();
_
stdio
.
stdout
.
write
(
'
\n
'
);
_
writeToStdOut
(
'
\n
'
);
}
/// Print summary information when a task is done.
...
...
@@ -1026,16 +1039,20 @@ class AnsiStatus extends AnsiSpinner {
/// line before writing the elapsed time.
void
writeSummaryInformation
()
{
if
(
multilineOutput
)
{
_
stdio
.
stdout
.
write
(
'
\n
${'$message Done'.padRight(padding)}$_margin
'
);
_
writeToStdOut
(
'
\n
${'$message Done'.padRight(padding)}$_margin
'
);
}
_
stdio
.
stdout
.
write
(
elapsedTime
.
padLeft
(
_kTimePadding
));
_
writeToStdOut
(
elapsedTime
.
padLeft
(
_kTimePadding
));
if
(
seemsSlow
)
{
_
stdio
.
stdout
.
write
(
' (!)'
);
_
writeToStdOut
(
' (!)'
);
}
}
void
_clearStatus
()
{
_stdio
.
stdout
.
write
(
'
${_backspaceChar * _totalMessageLength}${_clearChar * _totalMessageLength}${_backspaceChar * _totalMessageLength}
'
);
_writeToStdOut
(
'
${_backspaceChar * _totalMessageLength}
'
'
${_clearChar * _totalMessageLength}
'
'
${_backspaceChar * _totalMessageLength}
'
,
);
}
@override
...
...
packages/flutter_tools/lib/src/commands/daemon.dart
View file @
93a5b7d4
...
...
@@ -143,7 +143,7 @@ class Daemon {
final
dynamic
id
=
request
[
'id'
];
if
(
id
==
null
)
{
s
tderr
.
writeln
(
'no id for request:
$request
'
);
s
afeStdioWrite
(
stderr
,
'no id for request:
$request
\n
'
);
return
;
}
...
...
@@ -323,9 +323,9 @@ class DaemonDomain extends Domain {
// capture the print output for testing.
print
(
message
.
message
);
}
else
if
(
message
.
level
==
'error'
)
{
s
tderr
.
writeln
(
message
.
message
);
s
afeStdioWrite
(
stderr
,
'
${message.message}
\n
'
);
if
(
message
.
stackTrace
!=
null
)
{
s
tderr
.
writeln
(
message
.
stackTrace
.
toString
().
trimRight
()
);
s
afeStdioWrite
(
stderr
,
'
${message.stackTrace.toString().trimRight()}
\n
'
);
}
}
}
else
{
...
...
@@ -872,7 +872,13 @@ Stream<Map<String, dynamic>> get stdinCommandStream => stdin
});
void
stdoutCommandResponse
(
Map
<
String
,
dynamic
>
command
)
{
stdout
.
writeln
(
'[
${jsonEncodeObject(command)}
]'
);
safeStdioWrite
(
stdout
,
'[
${jsonEncodeObject(command)}
]
\n
'
,
fallback:
(
String
message
,
dynamic
error
,
StackTrace
stack
)
{
throwToolExit
(
'Failed to write daemon command response to stdout:
$error
'
);
},
);
}
String
jsonEncodeObject
(
dynamic
object
)
{
...
...
packages/flutter_tools/lib/src/commands/shell_completion.dart
View file @
93a5b7d4
...
...
@@ -49,7 +49,8 @@ class ShellCompletionCommand extends FlutterCommand {
}
if
(
argResults
.
rest
.
isEmpty
||
argResults
.
rest
.
first
==
'-'
)
{
stdout
.
write
(
generateCompletionScript
(<
String
>[
'flutter'
]));
final
String
script
=
generateCompletionScript
(<
String
>[
'flutter'
]);
safeStdioWrite
(
stdout
,
script
);
return
FlutterCommandResult
.
warning
();
}
...
...
packages/flutter_tools/test/general.shard/base/logger_test.dart
View file @
93a5b7d4
...
...
@@ -5,12 +5,14 @@
import
'dart:convert'
show
jsonEncode
;
import
'package:platform/platform.dart'
;
import
'package:flutter_tools/src/base/io.dart'
;
import
'package:flutter_tools/src/base/logger.dart'
;
import
'package:flutter_tools/src/base/terminal.dart'
;
import
'package:mockito/mockito.dart'
;
import
'package:quiver/testing/async.dart'
;
import
'../../src/common.dart'
;
import
'../../src/mocks.dart'
;
import
'../../src/mocks.dart'
as
mocks
;
final
Platform
_kNoAnsiPlatform
=
FakePlatform
.
fromPlatform
(
const
LocalPlatform
())..
stdoutSupportsAnsi
=
false
;
final
String
red
=
RegExp
.
escape
(
AnsiTerminal
.
red
);
...
...
@@ -18,6 +20,9 @@ final String bold = RegExp.escape(AnsiTerminal.bold);
final
String
resetBold
=
RegExp
.
escape
(
AnsiTerminal
.
resetBold
);
final
String
resetColor
=
RegExp
.
escape
(
AnsiTerminal
.
resetColor
);
class
MockStdio
extends
Mock
implements
Stdio
{}
class
MockStdout
extends
Mock
implements
Stdout
{}
void
main
(
)
{
group
(
'AppContext'
,
()
{
FakeStopwatch
fakeStopWatch
;
...
...
@@ -25,10 +30,11 @@ void main() {
setUp
(()
{
fakeStopWatch
=
FakeStopwatch
();
});
testWithoutContext
(
'error'
,
()
async
{
final
BufferLogger
mockLogger
=
BufferLogger
(
terminal:
AnsiTerminal
(
stdio:
MockStdio
(),
stdio:
mocks
.
MockStdio
(),
platform:
_kNoAnsiPlatform
,
),
outputPreferences:
OutputPreferences
.
test
(
showColor:
false
),
...
...
@@ -51,7 +57,7 @@ void main() {
testWithoutContext
(
'ANSI colored errors'
,
()
async
{
final
BufferLogger
mockLogger
=
BufferLogger
(
terminal:
AnsiTerminal
(
stdio:
MockStdio
(),
stdio:
mocks
.
MockStdio
(),
platform:
FakePlatform
()..
stdoutSupportsAnsi
=
true
,
),
outputPreferences:
OutputPreferences
.
test
(
showColor:
true
),
...
...
@@ -75,8 +81,40 @@ void main() {
});
});
testWithoutContext
(
'Logger does not throw when stdio write throws'
,
()
async
{
final
MockStdio
stdio
=
MockStdio
();
final
MockStdout
stdout
=
MockStdout
();
final
MockStdout
stderr
=
MockStdout
();
bool
stdoutThrew
=
false
;
bool
stderrThrew
=
false
;
when
(
stdio
.
stdout
).
thenReturn
(
stdout
);
when
(
stdio
.
stderr
).
thenReturn
(
stderr
);
when
(
stdout
.
write
(
any
)).
thenAnswer
((
_
)
{
stdoutThrew
=
true
;
throw
'Error'
;
});
when
(
stderr
.
write
(
any
)).
thenAnswer
((
_
)
{
stderrThrew
=
true
;
throw
'Error'
;
});
final
Logger
logger
=
StdoutLogger
(
terminal:
AnsiTerminal
(
stdio:
stdio
,
platform:
_kNoAnsiPlatform
,
),
stdio:
stdio
,
outputPreferences:
OutputPreferences
.
test
(),
timeoutConfiguration:
const
TimeoutConfiguration
(),
platform:
FakePlatform
(),
);
logger
.
printStatus
(
'message'
);
logger
.
printError
(
'error message'
);
expect
(
stdoutThrew
,
true
);
expect
(
stderrThrew
,
true
);
});
group
(
'Spinners'
,
()
{
MockStdio
mockStdio
;
mocks
.
MockStdio
mockStdio
;
FakeStopwatch
mockStopwatch
;
FakeStopwatchFactory
stopwatchFactory
;
int
called
;
...
...
@@ -85,7 +123,7 @@ void main() {
setUp
(()
{
mockStopwatch
=
FakeStopwatch
();
mockStdio
=
MockStdio
();
mockStdio
=
mocks
.
MockStdio
();
called
=
0
;
stopwatchFactory
=
FakeStopwatchFactory
(
mockStopwatch
);
});
...
...
@@ -375,14 +413,15 @@ void main() {
});
}
});
group
(
'Output format'
,
()
{
MockStdio
mockStdio
;
mocks
.
MockStdio
mockStdio
;
SummaryStatus
summaryStatus
;
int
called
;
final
RegExp
secondDigits
=
RegExp
(
r'[^\b]\b\b\b\b\b[0-9]+[.][0-9]+(?:s|ms)'
);
setUp
(()
{
mockStdio
=
MockStdio
();
mockStdio
=
mocks
.
MockStdio
();
called
=
0
;
summaryStatus
=
SummaryStatus
(
message:
'Hello world'
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment