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

Side by Side Diff: pkg/dev_compiler/tool/input_sdk/lib/io/process.dart

Issue 2698353003: unfork DDC's copy of most SDK libraries (Closed)
Patch Set: revert core_patch Created 3 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
OLDNEW
(Empty)
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
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.
4
5 part of dart.io;
6
7 // TODO(ager): The only reason for this class is that we
8 // cannot patch a top-level at this point.
9 class _ProcessUtils {
10 external static void _exit(int status);
11 external static void _setExitCode(int status);
12 external static int _getExitCode();
13 external static void _sleep(int millis);
14 external static int _pid(Process process);
15 external static Stream<ProcessSignal> _watchSignal(ProcessSignal signal);
16 }
17
18 /**
19 * Exit the Dart VM process immediately with the given exit code.
20 *
21 * This does not wait for any asynchronous operations to terminate. Using
22 * [exit] is therefore very likely to lose data.
23 *
24 * The handling of exit codes is platform specific.
25 *
26 * On Linux and OS X an exit code for normal termination will always
27 * be in the range [0..255]. If an exit code outside this range is
28 * set the actual exit code will be the lower 8 bits masked off and
29 * treated as an unsigned value. E.g. using an exit code of -1 will
30 * result in an actual exit code of 255 being reported.
31 *
32 * On Windows the exit code can be set to any 32-bit value. However
33 * some of these values are reserved for reporting system errors like
34 * crashes.
35 *
36 * Besides this the Dart executable itself uses an exit code of `254`
37 * for reporting compile time errors and an exit code of `255` for
38 * reporting runtime error (unhandled exception).
39 *
40 * Due to these facts it is recommended to only use exit codes in the
41 * range [0..127] for communicating the result of running a Dart
42 * program to the surrounding environment. This will avoid any
43 * cross-platform issues.
44 */
45 void exit(int code) {
46 if (code is !int) {
47 throw new ArgumentError("Integer value for exit code expected");
48 }
49 _ProcessUtils._exit(code);
50 }
51
52 /**
53 * Set the global exit code for the Dart VM.
54 *
55 * The exit code is global for the Dart VM and the last assignment to
56 * exitCode from any isolate determines the exit code of the Dart VM
57 * on normal termination.
58 *
59 * Default value is `0`.
60 *
61 * See [exit] for more information on how to chose a value for the
62 * exit code.
63 */
64 void set exitCode(int code) {
65 if (code is !int) {
66 throw new ArgumentError("Integer value for exit code expected");
67 }
68 _ProcessUtils._setExitCode(code);
69 }
70
71 /**
72 * Get the global exit code for the Dart VM.
73 *
74 * The exit code is global for the Dart VM and the last assignment to
75 * exitCode from any isolate determines the exit code of the Dart VM
76 * on normal termination.
77 *
78 * See [exit] for more information on how to chose a value for the
79 * exit code.
80 */
81 int get exitCode => _ProcessUtils._getExitCode();
82
83 /**
84 * Sleep for the duration specified in [duration].
85 *
86 * Use this with care, as no asynchronous operations can be processed
87 * in a isolate while it is blocked in a [sleep] call.
88 */
89 void sleep(Duration duration) {
90 int milliseconds = duration.inMilliseconds;
91 if (milliseconds < 0) {
92 throw new ArgumentError("sleep: duration cannot be negative");
93 }
94 _ProcessUtils._sleep(milliseconds);
95 }
96
97 /**
98 * Returns the PID of the current process.
99 */
100 int get pid => _ProcessUtils._pid(null);
101
102 /**
103 * Modes for running a new process.
104 */
105 enum ProcessStartMode {
106 /// Normal child process.
107 NORMAL,
108 /// Detached child process with no open communication channel.
109 DETACHED,
110 /// Detached child process with stdin, stdout and stderr still open
111 /// for communication with the child.
112 DETACHED_WITH_STDIO
113 }
114
115 /**
116 * The means to execute a program.
117 *
118 * Use the static [start] and [run] methods to start a new process.
119 * The run method executes the process non-interactively to completion.
120 * In contrast, the start method allows your code to interact with the
121 * running process.
122 *
123 * ## Start a process with the run method
124 *
125 * The following code sample uses the run method to create a process
126 * that runs the UNIX command `ls`, which lists the contents of a directory.
127 * The run method completes with a [ProcessResult] object when the process
128 * terminates. This provides access to the output and exit code from the
129 * process. The run method does not return a Process object; this prevents your
130 * code from interacting with the running process.
131 *
132 * import 'dart:io';
133 *
134 * main() {
135 * // List all files in the current directory in UNIX-like systems.
136 * Process.run('ls', ['-l']).then((ProcessResult results) {
137 * print(results.stdout);
138 * });
139 * }
140 *
141 * ## Start a process with the start method
142 *
143 * The following example uses start to create the process.
144 * The start method returns a [Future] for a Process object.
145 * When the future completes the process is started and
146 * your code can interact with the
147 * Process: writing to stdin, listening to stdout, and so on.
148 *
149 * The following sample starts the UNIX `cat` utility, which when given no
150 * command-line arguments, echos its input.
151 * The program writes to the process's standard input stream
152 * and prints data from its standard output stream.
153 *
154 * import 'dart:io';
155 * import 'dart:convert';
156 *
157 * main() {
158 * Process.start('cat', []).then((Process process) {
159 * process.stdout
160 * .transform(UTF8.decoder)
161 * .listen((data) { print(data); });
162 * process.stdin.writeln('Hello, world!');
163 * process.stdin.writeln('Hello, galaxy!');
164 * process.stdin.writeln('Hello, universe!');
165 * });
166 * }
167 *
168 * ## Standard I/O streams
169 *
170 * As seen in the previous code sample, you can interact with the Process's
171 * standard output stream through the getter [stdout],
172 * and you can interact with the Process's standard input stream through
173 * the getter [stdin].
174 * In addition, Process provides a getter [stderr] for using the Process's
175 * standard error stream.
176 *
177 * A Process's streams are distinct from the top-level streams
178 * for the current program.
179 *
180 * ## Exit codes
181 *
182 * Call the [exitCode] method to get the exit code of the process.
183 * The exit code indicates whether the program terminated successfully
184 * (usually indicated with an exit code of 0) or with an error.
185 *
186 * If the start method is used, the exitCode is available through a future
187 * on the Process object (as shown in the example below).
188 * If the run method is used, the exitCode is available
189 * through a getter on the ProcessResult instance.
190 *
191 * import 'dart:io';
192 *
193 * main() {
194 * Process.start('ls', ['-l']).then((process) {
195 * // Get the exit code from the new process.
196 * process.exitCode.then((exitCode) {
197 * print('exit code: $exitCode');
198 * });
199 * });
200 * }
201 *
202 * ## Other resources
203 *
204 * [Dart by Example](https://www.dartlang.org/dart-by-example/#dart-io-and-comma nd-line-apps)
205 * provides additional task-oriented code samples that show how to use
206 * various API from the [dart:io] library.
207 */
208 abstract class Process {
209 /**
210 * Returns a [:Future:] which completes with the exit code of the process
211 * when the process completes.
212 *
213 * The handling of exit codes is platform specific.
214 *
215 * On Linux and OS X a normal exit code will be a positive value in
216 * the range [0..255]. If the process was terminated due to a signal
217 * the exit code will be a negative value in the range [-255..-1],
218 * where the absolute value of the exit code is the signal
219 * number. For example, if a process crashes due to a segmentation
220 * violation the exit code will be -11, as the signal SIGSEGV has the
221 * number 11.
222 *
223 * On Windows a process can report any 32-bit value as an exit
224 * code. When returning the exit code this exit code is turned into
225 * a signed value. Some special values are used to report
226 * termination due to some system event. E.g. if a process crashes
227 * due to an access violation the 32-bit exit code is `0xc0000005`,
228 * which will be returned as the negative number `-1073741819`. To
229 * get the original 32-bit value use `(0x100000000 + exitCode) &
230 * 0xffffffff`.
231 */
232 Future<int> exitCode;
233
234 /**
235 * Starts a process running the [executable] with the specified
236 * [arguments]. Returns a [:Future<Process>:] that completes with a
237 * Process instance when the process has been successfully
238 * started. That [Process] object can be used to interact with the
239 * process. If the process cannot be started the returned [Future]
240 * completes with an exception.
241 *
242 * Use [workingDirectory] to set the working directory for the process. Note
243 * that the change of directory occurs before executing the process on some
244 * platforms, which may have impact when using relative paths for the
245 * executable and the arguments.
246 *
247 * Use [environment] to set the environment variables for the process. If not
248 * set the environment of the parent process is inherited. Currently, only
249 * US-ASCII environment variables are supported and errors are likely to occur
250 * if an environment variable with code-points outside the US-ASCII range is
251 * passed in.
252 *
253 * If [includeParentEnvironment] is `true`, the process's environment will
254 * include the parent process's environment, with [environment] taking
255 * precedence. Default is `true`.
256 *
257 * If [runInShell] is `true`, the process will be spawned through a system
258 * shell. On Linux and OS X, [:/bin/sh:] is used, while
259 * [:%WINDIR%\system32\cmd.exe:] is used on Windows.
260 *
261 * Users must read all data coming on the [stdout] and [stderr]
262 * streams of processes started with [:Process.start:]. If the user
263 * does not read all data on the streams the underlying system
264 * resources will not be released since there is still pending data.
265 *
266 * The following code uses `Process.start` to grep for `main` in the
267 * file `test.dart` on Linux.
268 *
269 * Process.start('grep', ['-i', 'main', 'test.dart']).then((process) {
270 * stdout.addStream(process.stdout);
271 * stderr.addStream(process.stderr);
272 * });
273 *
274 * If [mode] is [ProcessStartMode.NORMAL] (the default) a child
275 * process will be started with `stdin`, `stdout` and `stderr`
276 * connected.
277 *
278 * If `mode` is [ProcessStartMode.DETACHED] a detached process will
279 * be created. A detached process has no connection to its parent,
280 * and can keep running on its own when the parent dies. The only
281 * information available from a detached process is its `pid`. There
282 * is no connection to its `stdin`, `stdout` or `stderr`, nor will
283 * the process' exit code become available when it terminates.
284 *
285 * If `mode` is [ProcessStartMode.DETACHED_WITH_STDIO] a detached
286 * process will be created where the `stdin`, `stdout` and `stderr`
287 * are connected. The creator can communicate with the child through
288 * these. The detached process will keep running even if these
289 * communication channels are closed. The process' exit code will
290 * not become available when it terminated.
291 *
292 * The default value for `mode` is `ProcessStartMode.NORMAL`.
293 */
294 external static Future<Process> start(
295 String executable,
296 List<String> arguments,
297 {String workingDirectory,
298 Map<String, String> environment,
299 bool includeParentEnvironment: true,
300 bool runInShell: false,
301 ProcessStartMode mode: ProcessStartMode.NORMAL});
302
303 /**
304 * Starts a process and runs it non-interactively to completion. The
305 * process run is [executable] with the specified [arguments].
306 *
307 * Use [workingDirectory] to set the working directory for the process. Note
308 * that the change of directory occurs before executing the process on some
309 * platforms, which may have impact when using relative paths for the
310 * executable and the arguments.
311 *
312 * Use [environment] to set the environment variables for the process. If not
313 * set the environment of the parent process is inherited. Currently, only
314 * US-ASCII environment variables are supported and errors are likely to occur
315 * if an environment variable with code-points outside the US-ASCII range is
316 * passed in.
317 *
318 * If [includeParentEnvironment] is `true`, the process's environment will
319 * include the parent process's environment, with [environment] taking
320 * precedence. Default is `true`.
321 *
322 * If [runInShell] is true, the process will be spawned through a system
323 * shell. On Linux and OS X, `/bin/sh` is used, while
324 * `%WINDIR%\system32\cmd.exe` is used on Windows.
325 *
326 * The encoding used for decoding `stdout` and `stderr` into text is
327 * controlled through [stdoutEncoding] and [stderrEncoding]. The
328 * default encoding is [SYSTEM_ENCODING]. If `null` is used no
329 * decoding will happen and the [ProcessResult] will hold binary
330 * data.
331 *
332 * Returns a `Future<ProcessResult>` that completes with the
333 * result of running the process, i.e., exit code, standard out and
334 * standard in.
335 *
336 * The following code uses `Process.run` to grep for `main` in the
337 * file `test.dart` on Linux.
338 *
339 * Process.run('grep', ['-i', 'main', 'test.dart']).then((result) {
340 * stdout.write(result.stdout);
341 * stderr.write(result.stderr);
342 * });
343 */
344 external static Future<ProcessResult> run(
345 String executable,
346 List<String> arguments,
347 {String workingDirectory,
348 Map<String, String> environment,
349 bool includeParentEnvironment: true,
350 bool runInShell: false,
351 Encoding stdoutEncoding: SYSTEM_ENCODING,
352 Encoding stderrEncoding: SYSTEM_ENCODING});
353
354
355 /**
356 * Starts a process and runs it to completion. This is a synchronous
357 * call and will block until the child process terminates.
358 *
359 * The arguments are the same as for `Process.run`.
360 *
361 * Returns a `ProcessResult` with the result of running the process,
362 * i.e., exit code, standard out and standard in.
363 */
364 external static ProcessResult runSync(
365 String executable,
366 List<String> arguments,
367 {String workingDirectory,
368 Map<String, String> environment,
369 bool includeParentEnvironment: true,
370 bool runInShell: false,
371 Encoding stdoutEncoding: SYSTEM_ENCODING,
372 Encoding stderrEncoding: SYSTEM_ENCODING});
373
374 /**
375 * Kills the process with id [pid].
376 *
377 * Where possible, sends the [signal] to the process with id
378 * `pid`. This includes Linux and OS X. The default signal is
379 * [ProcessSignal.SIGTERM] which will normally terminate the
380 * process.
381 *
382 * On platforms without signal support, including Windows, the call
383 * just terminates the process with id `pid` in a platform specific
384 * way, and the `signal` parameter is ignored.
385 *
386 * Returns `true` if the signal is successfully delivered to the
387 * process. Otherwise the signal could not be sent, usually meaning
388 * that the process is already dead.
389 */
390 external static bool killPid(
391 int pid, [ProcessSignal signal = ProcessSignal.SIGTERM]);
392
393 /**
394 * Returns the standard output stream of the process as a [:Stream:].
395 */
396 Stream<List<int>> get stdout;
397
398 /**
399 * Returns the standard error stream of the process as a [:Stream:].
400 */
401 Stream<List<int>> get stderr;
402
403 /**
404 * Returns the standard input stream of the process as an [IOSink].
405 */
406 IOSink get stdin;
407
408 /**
409 * Returns the process id of the process.
410 */
411 int get pid;
412
413 /**
414 * Kills the process.
415 *
416 * Where possible, sends the [signal] to the process. This includes
417 * Linux and OS X. The default signal is [ProcessSignal.SIGTERM]
418 * which will normally terminate the process.
419 *
420 * On platforms without signal support, including Windows, the call
421 * just terminates the process in a platform specific way, and the
422 * `signal` parameter is ignored.
423 *
424 * Returns `true` if the signal is successfully delivered to the
425 * process. Otherwise the signal could not be sent, usually meaning
426 * that the process is already dead.
427 */
428 bool kill([ProcessSignal signal = ProcessSignal.SIGTERM]);
429 }
430
431
432 /**
433 * [ProcessResult] represents the result of running a non-interactive
434 * process started with [Process.run] or [Process.runSync].
435 */
436 class ProcessResult {
437 /**
438 * Exit code for the process.
439 *
440 * See [Process.exitCode] for more information in the exit code
441 * value.
442 */
443 final int exitCode;
444
445 /**
446 * Standard output from the process. The value used for the
447 * `stdoutEncoding` argument to `Process.run` determines the type. If
448 * `null` was used this value is of type `List<int> otherwise it is
449 * of type `String`.
450 */
451 final stdout;
452
453 /**
454 * Standard error from the process. The value used for the
455 * `stderrEncoding` argument to `Process.run` determines the type. If
456 * `null` was used this value is of type `List<int>
457 * otherwise it is of type `String`.
458 */
459 final stderr;
460
461 /**
462 * Process id of the process.
463 */
464 final int pid;
465
466 ProcessResult(this.pid, this.exitCode, this.stdout, this.stderr);
467 }
468
469
470 /**
471 * On Posix systems, [ProcessSignal] is used to send a specific signal
472 * to a child process, see [:Process.kill:].
473 *
474 * Some [ProcessSignal]s can also be watched, as a way to intercept the default
475 * signal handler and implement another. See [ProcessSignal.watch] for more
476 * information.
477 */
478 class ProcessSignal {
479 static const ProcessSignal SIGHUP = const ProcessSignal._(1, "SIGHUP");
480 static const ProcessSignal SIGINT = const ProcessSignal._(2, "SIGINT");
481 static const ProcessSignal SIGQUIT = const ProcessSignal._(3, "SIGQUIT");
482 static const ProcessSignal SIGILL = const ProcessSignal._(4, "SIGILL");
483 static const ProcessSignal SIGTRAP = const ProcessSignal._(5, "SIGTRAP");
484 static const ProcessSignal SIGABRT = const ProcessSignal._(6, "SIGABRT");
485 static const ProcessSignal SIGBUS = const ProcessSignal._(7, "SIGBUS");
486 static const ProcessSignal SIGFPE = const ProcessSignal._(8, "SIGFPE");
487 static const ProcessSignal SIGKILL = const ProcessSignal._(9, "SIGKILL");
488 static const ProcessSignal SIGUSR1 = const ProcessSignal._(10, "SIGUSR1");
489 static const ProcessSignal SIGSEGV = const ProcessSignal._(11, "SIGSEGV");
490 static const ProcessSignal SIGUSR2 = const ProcessSignal._(12, "SIGUSR2");
491 static const ProcessSignal SIGPIPE = const ProcessSignal._(13, "SIGPIPE");
492 static const ProcessSignal SIGALRM = const ProcessSignal._(14, "SIGALRM");
493 static const ProcessSignal SIGTERM = const ProcessSignal._(15, "SIGTERM");
494 static const ProcessSignal SIGCHLD = const ProcessSignal._(17, "SIGCHLD");
495 static const ProcessSignal SIGCONT = const ProcessSignal._(18, "SIGCONT");
496 static const ProcessSignal SIGSTOP = const ProcessSignal._(19, "SIGSTOP");
497 static const ProcessSignal SIGTSTP = const ProcessSignal._(20, "SIGTSTP");
498 static const ProcessSignal SIGTTIN = const ProcessSignal._(21, "SIGTTIN");
499 static const ProcessSignal SIGTTOU = const ProcessSignal._(22, "SIGTTOU");
500 static const ProcessSignal SIGURG = const ProcessSignal._(23, "SIGURG");
501 static const ProcessSignal SIGXCPU = const ProcessSignal._(24, "SIGXCPU");
502 static const ProcessSignal SIGXFSZ = const ProcessSignal._(25, "SIGXFSZ");
503 static const ProcessSignal SIGVTALRM = const ProcessSignal._(26, "SIGVTALRM");
504 static const ProcessSignal SIGPROF = const ProcessSignal._(27, "SIGPROF");
505 static const ProcessSignal SIGWINCH = const ProcessSignal._(28, "SIGWINCH");
506 static const ProcessSignal SIGPOLL = const ProcessSignal._(29, "SIGPOLL");
507 static const ProcessSignal SIGSYS = const ProcessSignal._(31, "SIGSYS");
508
509 final int _signalNumber;
510 final String _name;
511
512 const ProcessSignal._(this._signalNumber, this._name);
513
514 String toString() => _name;
515
516 /**
517 * Watch for process signals.
518 *
519 * The following [ProcessSignal]s can be listened to:
520 *
521 * * [ProcessSignal.SIGHUP].
522 * * [ProcessSignal.SIGINT]. Signal sent by e.g. CTRL-C.
523 * * [ProcessSignal.SIGTERM]. Not available on Windows.
524 * * [ProcessSignal.SIGUSR1]. Not available on Windows.
525 * * [ProcessSignal.SIGUSR2]. Not available on Windows.
526 * * [ProcessSignal.SIGWINCH]. Not available on Windows.
527 *
528 * Other signals are disallowed, as they may be used by the VM.
529 *
530 * A signal can be watched multiple times, from multiple isolates, where all
531 * callbacks are invoked when signaled, in no specific order.
532 */
533 Stream<ProcessSignal> watch() => _ProcessUtils._watchSignal(this);
534 }
535
536
537 class SignalException implements IOException {
538 final String message;
539 final osError;
540
541 const SignalException(this.message, [this.osError = null]);
542
543 String toString() {
544 var msg = "";
545 if (osError != null) {
546 msg = ", osError: $osError";
547 }
548 return "SignalException: $message$msg";
549 }
550 }
551
552
553 class ProcessException implements IOException {
554 /**
555 * Contains the executable provided for the process.
556 */
557 final String executable;
558
559 /**
560 * Contains the arguments provided for the process.
561 */
562 final List<String> arguments;
563
564 /**
565 * Contains the system message for the process exception if any.
566 */
567 final String message;
568
569 /**
570 * Contains the OS error code for the process exception if any.
571 */
572 final int errorCode;
573
574 const ProcessException(this.executable, this.arguments, [this.message = "",
575 this.errorCode = 0]);
576 String toString() {
577 var msg = (message == null) ? 'OS error code: $errorCode' : message;
578 var args = arguments.join(' ');
579 return "ProcessException: $msg\n Command: $executable $args";
580 }
581 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698