Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(978)

Side by Side Diff: pkg/scheduled_test/lib/scheduled_process.dart

Issue 12741004: Accommodate a race condition in pkg/scheduled_test/scheduled_process_test. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Remove a bad timeout Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | pkg/scheduled_test/lib/src/utils.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library scheduled_process; 5 library scheduled_process;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:io'; 8 import 'dart:io';
9 9
10 import 'scheduled_test.dart'; 10 import 'scheduled_test.dart';
(...skipping 20 matching lines...) Expand all
31 /// The process that's scheduled to run. 31 /// The process that's scheduled to run.
32 ValueFuture<Process> _process; 32 ValueFuture<Process> _process;
33 33
34 /// A fork of [_stdout] that records the standard output of the process. Used 34 /// A fork of [_stdout] that records the standard output of the process. Used
35 /// for debugging information. 35 /// for debugging information.
36 Stream<String> _stdoutLog; 36 Stream<String> _stdoutLog;
37 37
38 /// A line-by-line view of the standard output stream of the process. 38 /// A line-by-line view of the standard output stream of the process.
39 Stream<String> _stdout; 39 Stream<String> _stdout;
40 40
41 /// A subscription that controls both [_stdout] and [_stdoutLog]. 41 /// A canceller that controls both [_stdout] and [_stdoutLog].
42 StreamSubscription<String> _stdoutSubscription; 42 StreamCanceller _stdoutCanceller;
43 43
44 /// A fork of [_stderr] that records the standard error of the process. Used 44 /// A fork of [_stderr] that records the standard error of the process. Used
45 /// for debugging information. 45 /// for debugging information.
46 Stream<String> _stderrLog; 46 Stream<String> _stderrLog;
47 47
48 /// A line-by-line view of the standard error stream of the process. 48 /// A line-by-line view of the standard error stream of the process.
49 Stream<String> _stderr; 49 Stream<String> _stderr;
50 50
51 /// A subscription that controls both [_stderr] and [_stderrLog]. 51 /// A canceller that controls both [_stderr] and [_stderrLog].
52 StreamSubscription<String> _stderrSubscription; 52 StreamCanceller _stderrCanceller;
53 53
54 /// The exit code of the process that's scheduled to run. This will naturally 54 /// The exit code of the process that's scheduled to run. This will naturally
55 /// only complete once the process has terminated. 55 /// only complete once the process has terminated.
56 ValueFuture<int> _exitCode; 56 ValueFuture<int> _exitCode;
57 57
58 /// Whether the user has scheduled the end of this process by calling either 58 /// Whether the user has scheduled the end of this process by calling either
59 /// [shouldExit] or [kill]. 59 /// [shouldExit] or [kill].
60 var _endScheduled = false; 60 var _endScheduled = false;
61 61
62 /// The task that runs immediately before this process is scheduled to end. If 62 /// The task that runs immediately before this process is scheduled to end. If
(...skipping 17 matching lines...) Expand all
80 {options, String description, Encoding encoding: Encoding.UTF_8}) 80 {options, String description, Encoding encoding: Encoding.UTF_8})
81 : _encoding = encoding { 81 : _encoding = encoding {
82 assert(currentSchedule.state == ScheduleState.SET_UP); 82 assert(currentSchedule.state == ScheduleState.SET_UP);
83 83
84 _updateDescription(executable, arguments); 84 _updateDescription(executable, arguments);
85 85
86 _scheduleStartProcess(executable, arguments, options); 86 _scheduleStartProcess(executable, arguments, options);
87 87
88 _scheduleExceptionCleanup(); 88 _scheduleExceptionCleanup();
89 89
90 var stdoutWithSubscription = _lineStreamWithSubscription( 90 var stdoutWithCanceller = _lineStreamWithCanceller(
91 _process.then((p) => p.stdout)); 91 _process.then((p) => p.stdout));
92 _stdoutSubscription = stdoutWithSubscription.last; 92 _stdoutCanceller = stdoutWithCanceller.last;
93 var stdoutTee = tee(stdoutWithSubscription.first); 93 var stdoutTee = tee(stdoutWithCanceller.first);
94 _stdout = stdoutTee.first; 94 _stdout = stdoutTee.first;
95 _stdoutLog = stdoutTee.last; 95 _stdoutLog = stdoutTee.last;
96 96
97 var stderrWithSubscription = _lineStreamWithSubscription( 97 var stderrWithCanceller = _lineStreamWithCanceller(
98 _process.then((p) => p.stderr)); 98 _process.then((p) => p.stderr));
99 _stderrSubscription = stderrWithSubscription.last; 99 _stderrCanceller = stderrWithCanceller.last;
100 var stderrTee = tee(stderrWithSubscription.first); 100 var stderrTee = tee(stderrWithCanceller.first);
101 _stderr = stderrTee.first; 101 _stderr = stderrTee.first;
102 _stderrLog = stderrTee.last; 102 _stderrLog = stderrTee.last;
103 } 103 }
104 104
105 /// Updates [_description] to reflect [executable] and [arguments], which are 105 /// Updates [_description] to reflect [executable] and [arguments], which are
106 /// the same values as in [start]. 106 /// the same values as in [start].
107 void _updateDescription(executable, arguments) { 107 void _updateDescription(executable, arguments) {
108 if (executable is Future) { 108 if (executable is Future) {
109 _description = "future process"; 109 _description = "future process";
110 } else if (arguments is Future || arguments.any((e) => e is Future)) { 110 } else if (arguments is Future || arguments.any((e) => e is Future)) {
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 170
171 if (!_endExpected) { 171 if (!_endExpected) {
172 throw "Process '${this.description}' ended earlier than scheduled " 172 throw "Process '${this.description}' ended earlier than scheduled "
173 "with exit code $exitCode."; 173 "with exit code $exitCode.";
174 } 174 }
175 })); 175 }));
176 }); 176 });
177 } 177 }
178 178
179 /// Converts a stream of bytes to a stream of lines and returns that along 179 /// Converts a stream of bytes to a stream of lines and returns that along
180 /// with a [StreamSubscription] controlling it. 180 /// with a [StreamCanceller] controlling it.
181 Pair<Stream<String>, StreamSubscription<String>> _lineStreamWithSubscription( 181 Pair<Stream<String>, StreamCanceller> _lineStreamWithCanceller(
182 Future<Stream<int>> streamFuture) { 182 Future<Stream<int>> streamFuture) {
183 return streamWithSubscription(futureStream(streamFuture) 183 return streamWithCanceller(futureStream(streamFuture)
184 .handleError((e) => currentSchedule.signalError(e)) 184 .handleError((e) => currentSchedule.signalError(e))
185 .transform(new StringDecoder(_encoding)) 185 .transform(new StringDecoder(_encoding))
186 .transform(new LineTransformer())); 186 .transform(new LineTransformer()));
187 } 187 }
188 188
189 /// Schedule an exception handler that will clean up the process and provide 189 /// Schedule an exception handler that will clean up the process and provide
190 /// debug information if an error occurs. 190 /// debug information if an error occurs.
191 void _scheduleExceptionCleanup() { 191 void _scheduleExceptionCleanup() {
192 currentSchedule.onException.schedule(() { 192 currentSchedule.onException.schedule(() {
193 _stdoutSubscription.cancel(); 193 _stdoutCanceller();
194 _stderrSubscription.cancel(); 194 _stderrCanceller();
195 195
196 if (!_process.hasValue) return; 196 if (!_process.hasValue) return;
197 197
198 var killedPrematurely = false; 198 var killedPrematurely = false;
199 if (!_exitCode.hasValue) { 199 if (!_exitCode.hasValue) {
200 killedPrematurely = true; 200 killedPrematurely = true;
201 _endExpected = true; 201 _endExpected = true;
202 _process.value.kill(); 202 _process.value.kill();
203 // Ensure that the onException queue waits for the process to actually 203 // Ensure that the onException queue waits for the process to actually
204 // exit after being killed. 204 // exit after being killed.
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 schedule(() { 297 schedule(() {
298 _endExpected = true; 298 _endExpected = true;
299 return _exitCode.then((exitCode) { 299 return _exitCode.then((exitCode) {
300 if (expectedExitCode != null) { 300 if (expectedExitCode != null) {
301 expect(exitCode, equals(expectedExitCode)); 301 expect(exitCode, equals(expectedExitCode));
302 } 302 }
303 }); 303 });
304 }, "waiting for process '$description' to exit"); 304 }, "waiting for process '$description' to exit");
305 } 305 }
306 } 306 }
OLDNEW
« no previous file with comments | « no previous file | pkg/scheduled_test/lib/src/utils.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698