1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
//! # Process
//! Tasks that run other programs
use crate;
use OsStr;
/// Runs other programs
///
/// ## Behaviour
/// [`Process::run`] lets a child's output through to wherever
/// this program's own output goes and reports only how it
/// ended. [`Process::output`] pipes both streams and collects
/// them
///
/// Every task here runs on a sleep thread. Past `cores * 8`
/// of them, children queue rather than running at once
///
/// ## Settings
/// `input` feeds a child's standard input, `in_dir` starts it
/// somewhere else, and `env` or `env_only` decide what
/// environment it gets. Each keeps the last value it was given
///
/// ```no_run
/// # use atap::{Runtime, process::Process};
/// Runtime::task(
/// Process::output("/bin/sh", ["-c", "cat; pwd"])
/// .input(b"fed\n".as_slice())
/// .in_dir("/usr")
/// .env([("V", "set")]),
/// )
/// .spawn();
/// ```
///
/// ## Cancellation
/// A cancelled task kills its child's whole process group with
/// `SIGKILL`, reaps it, and gives back
/// [`RuntimeError::Cancelled`]. A task spawned with a timeout does
/// the same once its run is out of time, and reads
/// [`RuntimeError::TimedOut`]
///
/// ```no_run
/// # use atap::{Runtime, process::Process};
/// # use std::time::Duration;
/// let handle = Runtime::task(Process::run("/bin/sleep", ["60"]))
/// .timeout(Duration::from_secs(5))
/// .spawn();
/// ```
///
/// [`Runtime::block`] can't be cancelled or timed out, so a
/// blocking call on a child that never ends holds the calling
/// thread for as long as the child lives
///
/// #### Note
/// An error after the child started kills the child
///
/// [`RuntimeError::Cancelled`]: crate::RuntimeError::Cancelled
/// [`RuntimeError::TimedOut`]: crate::RuntimeError::TimedOut
/// [`Runtime::block`]: crate::Runtime::block
;