v2 / vlib / os / process_nix.c.v
185 lines · 161 sloc · 4.29 KB · 04d978575c57ba0de82eb7866a2663f4f9cbe540
Raw
1module os
2
3fn C.setpgid(pid i32, pgid i32) i32
4
5fn env_value_from_entries(env []string, name string) ?string {
6 prefix := '${name}='
7 for entry in env {
8 if entry.starts_with(prefix) {
9 return entry[prefix.len..]
10 }
11 }
12 return none
13}
14
15fn (p &Process) unix_resolve_filename() !string {
16 if is_abs_path(p.filename) {
17 return p.filename
18 }
19 if p.filename.contains(path_separator) {
20 if p.work_folder != '' {
21 return abs_path(p.filename)
22 }
23 return p.filename
24 }
25 path := env_value_from_entries(p.env, 'PATH') or { return error_failed_to_find_executable() }
26 return find_abs_path_of_executable_in_path_env(p.filename, path)
27}
28
29fn (mut p Process) unix_spawn_process() int {
30 mut pipeset := [6]int{}
31 if p.use_stdio_ctl {
32 mut dont_care := C.pipe(&pipeset[0]) // pipe read end 0 <- 1 pipe write end
33 dont_care = C.pipe(&pipeset[2]) // pipe read end 2 <- 3 pipe write end
34 dont_care = C.pipe(&pipeset[4]) // pipe read end 4 <- 5 pipe write end
35 _ = dont_care // using `_` directly on each above `pipe` fails to avoid C compiler generate an `-Wunused-result` warning
36 }
37 pid := fork()
38 if pid != 0 {
39 // This is the parent process after the fork.
40 // Note: pid contains the process ID of the child process
41 if p.use_stdio_ctl {
42 p.stdio_fd[0] = pipeset[1] // store the write end of child's in
43 p.stdio_fd[1] = pipeset[2] // store the read end of child's out
44 p.stdio_fd[2] = pipeset[4] // store the read end of child's err
45 // close the rest of the pipe fds, the parent does not need them
46 fd_close(pipeset[0])
47 fd_close(pipeset[3])
48 fd_close(pipeset[5])
49 }
50 return pid
51 }
52 //
53 // Here, we are in the child process.
54 // It still shares file descriptors with the parent process,
55 // but it is otherwise independent and can do stuff *without*
56 // affecting the parent process.
57 //
58 if p.use_pgroup {
59 C.setpgid(0, 0)
60 }
61 if p.use_stdio_ctl {
62 // Redirect the child standard in/out/err to the pipes that
63 // were created in the parent.
64 // Close the parent's pipe fds, the child do not need them:
65 fd_close(pipeset[1])
66 fd_close(pipeset[2])
67 fd_close(pipeset[4])
68 // redirect the pipe fds to the child's in/out/err fds:
69 C.dup2(pipeset[0], 0)
70 C.dup2(pipeset[3], 1)
71 C.dup2(pipeset[5], 2)
72 // close the pipe fdsx after the redirection
73 fd_close(pipeset[0])
74 fd_close(pipeset[3])
75 fd_close(pipeset[5])
76 }
77 p.filename = p.unix_resolve_filename() or {
78 eprintln(err)
79 exit(1)
80 }
81 if p.work_folder != '' {
82 chdir(p.work_folder) or {}
83 }
84 execve(p.filename, p.args, p.env) or {
85 eprintln(err)
86 exit(1)
87 }
88 return 0
89}
90
91fn (mut p Process) unix_stop_process() {
92 C.kill(p.pid, C.SIGSTOP)
93}
94
95fn (mut p Process) unix_resume_process() {
96 C.kill(p.pid, C.SIGCONT)
97}
98
99fn (mut p Process) unix_term_process() {
100 C.kill(p.pid, C.SIGTERM)
101}
102
103fn (mut p Process) unix_kill_process() {
104 C.kill(p.pid, C.SIGKILL)
105}
106
107fn (mut p Process) unix_kill_pgroup() {
108 C.kill(-p.pid, C.SIGKILL)
109}
110
111fn (mut p Process) unix_wait() {
112 p.impl_check_pid_status(false, 0)
113}
114
115fn (mut p Process) unix_is_alive() bool {
116 return p.impl_check_pid_status(true, C.WNOHANG)
117}
118
119fn (mut p Process) impl_check_pid_status(exit_early_on_ret0 bool, waitpid_options int) bool {
120 mut cstatus := 0
121 mut ret := -1
122 $if !emscripten ? {
123 ret = C.waitpid(p.pid, &cstatus, waitpid_options)
124 }
125 p.code = ret
126 if ret == -1 {
127 p.err = posix_get_error_msg(C.errno)
128 return false
129 }
130 if exit_early_on_ret0 && ret == 0 {
131 return true
132 }
133 mut pret, is_signaled := posix_wait4_to_exit_status(cstatus)
134 if is_signaled {
135 p.status = .aborted
136 p.err = 'Terminated by signal ${pret:2d} (${sigint_to_signal_name(pret)})'
137 pret += 128
138 } else {
139 p.status = .exited
140 }
141 p.code = pret
142 return false
143}
144
145// these are here to make v_win.c/v.c generation work in all cases:
146fn (mut p Process) win_spawn_process() int {
147 return 0
148}
149
150fn (mut p Process) win_stop_process() {
151}
152
153fn (mut p Process) win_resume_process() {
154}
155
156fn (mut p Process) win_term_process() {
157}
158
159fn (mut p Process) win_kill_process() {
160}
161
162fn (mut p Process) win_kill_pgroup() {
163}
164
165fn (mut p Process) win_wait() {
166}
167
168fn (mut p Process) win_is_alive() bool {
169 return false
170}
171
172fn (mut p Process) win_write_string(_idx int, _s string) {
173}
174
175fn (mut p Process) win_read_string(_idx int, _maxbytes int) (string, int) {
176 return '', 0
177}
178
179fn (mut p Process) win_is_pending(_idx int) bool {
180 return false
181}
182
183fn (mut p Process) win_slurp(_idx int) string {
184 return ''
185}
186