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