v / vlib / os
Raw file | 248 loc (225 sloc) | 5.24 KB | Latest commit hash 017ace6ea
1module os
2
3// signal_kill - kills the process, after that it is no longer running
4pub fn (mut p Process) signal_kill() {
5 if p.status !in [.running, .stopped] {
6 return
7 }
8 p._signal_kill()
9 p.status = .aborted
10 return
11}
12
13// signal_pgkill - kills the whole process group
14pub fn (mut p Process) signal_pgkill() {
15 if p.status !in [.running, .stopped] {
16 return
17 }
18 p._signal_pgkill()
19 return
20}
21
22// signal_stop - stops the process, you can resume it with p.signal_continue()
23pub fn (mut p Process) signal_stop() {
24 if p.status != .running {
25 return
26 }
27 p._signal_stop()
28 p.status = .stopped
29 return
30}
31
32// signal_continue - tell a stopped process to continue/resume its work
33pub fn (mut p Process) signal_continue() {
34 if p.status != .stopped {
35 return
36 }
37 p._signal_continue()
38 p.status = .running
39 return
40}
41
42// wait - wait for a process to finish.
43// Note: You have to call p.wait(), otherwise a finished process
44// would get to a zombie state, and its resources will not get
45// released fully, until its parent process exits.
46// Note: This call will block the calling process until the child
47// process is finished.
48pub fn (mut p Process) wait() {
49 if p.status == .not_started {
50 p._spawn()
51 }
52 if p.status !in [.running, .stopped] {
53 return
54 }
55 p._wait()
56 return
57}
58
59// close - free the OS resources associated with the process.
60// Can be called multiple times, but will free the resources just once.
61// This sets the process state to .closed, which is final.
62pub fn (mut p Process) close() {
63 if p.status in [.not_started, .closed] {
64 return
65 }
66 p.status = .closed
67 $if !windows {
68 for i in 0 .. 3 {
69 if p.stdio_fd[i] != 0 {
70 fd_close(p.stdio_fd[i])
71 }
72 }
73 }
74}
75
76[unsafe]
77pub fn (mut p Process) free() {
78 p.close()
79 unsafe {
80 p.filename.free()
81 p.err.free()
82 p.args.free()
83 p.env.free()
84 }
85}
86
87//
88// _spawn - should not be called directly, but only by p.run()/p.wait() .
89// It encapsulates the fork/execve mechanism that allows the
90// asynchronous starting of the new child process.
91fn (mut p Process) _spawn() int {
92 if !p.env_is_custom {
93 p.env = []string{}
94 current_environment := environ()
95 for k, v in current_environment {
96 p.env << '${k}=${v}'
97 }
98 }
99 mut pid := 0
100 $if windows {
101 pid = p.win_spawn_process()
102 } $else {
103 pid = p.unix_spawn_process()
104 }
105 p.pid = pid
106 p.status = .running
107 return 0
108}
109
110// is_alive - query whether the process p.pid is still alive
111pub fn (mut p Process) is_alive() bool {
112 if p.status in [.running, .stopped] {
113 return p._is_alive()
114 }
115 return false
116}
117
118//
119pub fn (mut p Process) set_redirect_stdio() {
120 p.use_stdio_ctl = true
121 return
122}
123
124pub fn (mut p Process) stdin_write(s string) {
125 p._check_redirection_call('stdin_write')
126 $if windows {
127 p.win_write_string(0, s)
128 } $else {
129 fd_write(p.stdio_fd[0], s)
130 }
131}
132
133// will read from stdout pipe, will only return when EOF (end of file) or data
134// means this will block unless there is data
135pub fn (mut p Process) stdout_slurp() string {
136 p._check_redirection_call('stdout_slurp')
137 $if windows {
138 return p.win_slurp(1)
139 } $else {
140 return fd_slurp(p.stdio_fd[1]).join('')
141 }
142}
143
144// read from stderr pipe, wait for data or EOF
145pub fn (mut p Process) stderr_slurp() string {
146 p._check_redirection_call('stderr_slurp')
147 $if windows {
148 return p.win_slurp(2)
149 } $else {
150 return fd_slurp(p.stdio_fd[2]).join('')
151 }
152}
153
154// read from stdout, return if data or not
155pub fn (mut p Process) stdout_read() string {
156 p._check_redirection_call('stdout_read')
157 $if windows {
158 s, _ := p.win_read_string(1, 4096)
159 return s
160 } $else {
161 s, _ := fd_read(p.stdio_fd[1], 4096)
162 return s
163 }
164}
165
166pub fn (mut p Process) stderr_read() string {
167 p._check_redirection_call('stderr_read')
168 $if windows {
169 s, _ := p.win_read_string(2, 4096)
170 return s
171 } $else {
172 s, _ := fd_read(p.stdio_fd[2], 4096)
173 return s
174 }
175}
176
177// _check_redirection_call - should be called just by stdxxx methods
178fn (mut p Process) _check_redirection_call(fn_name string) {
179 if !p.use_stdio_ctl {
180 panic('Call p.set_redirect_stdio() before calling p.${fn_name}')
181 }
182 if p.status == .not_started {
183 panic('Call p.${fn_name}() after you have called p.run()')
184 }
185}
186
187// _signal_stop - should not be called directly, except by p.signal_stop
188fn (mut p Process) _signal_stop() {
189 $if windows {
190 p.win_stop_process()
191 } $else {
192 p.unix_stop_process()
193 }
194}
195
196// _signal_continue - should not be called directly, just by p.signal_continue
197fn (mut p Process) _signal_continue() {
198 $if windows {
199 p.win_resume_process()
200 } $else {
201 p.unix_resume_process()
202 }
203}
204
205// _signal_kill - should not be called directly, except by p.signal_kill
206fn (mut p Process) _signal_kill() {
207 $if windows {
208 p.win_kill_process()
209 } $else {
210 p.unix_kill_process()
211 }
212}
213
214// _signal_pgkill - should not be called directly, except by p.signal_pgkill
215fn (mut p Process) _signal_pgkill() {
216 $if windows {
217 p.win_kill_pgroup()
218 } $else {
219 p.unix_kill_pgroup()
220 }
221}
222
223// _wait - should not be called directly, except by p.wait()
224fn (mut p Process) _wait() {
225 $if windows {
226 p.win_wait()
227 } $else {
228 p.unix_wait()
229 }
230}
231
232// _is_alive - should not be called directly, except by p.is_alive()
233fn (mut p Process) _is_alive() bool {
234 $if windows {
235 return p.win_is_alive()
236 } $else {
237 return p.unix_is_alive()
238 }
239}
240
241// run - starts the new process
242pub fn (mut p Process) run() {
243 if p.status != .not_started {
244 return
245 }
246 p._spawn()
247 return
248}