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
|
module os
fn C.setpgid(pid int, pgid int) int
fn (mut p Process) unix_spawn_process() int {
mut pipeset := [6]int{}
if p.use_stdio_ctl {
_ = C.pipe(&pipeset[0]) // pipe read end 0 <- 1 pipe write end
_ = C.pipe(&pipeset[2]) // pipe read end 2 <- 3 pipe write end
_ = C.pipe(&pipeset[4]) // pipe read end 4 <- 5 pipe write end
}
pid := fork()
if pid != 0 {
// This is the parent process after the fork.
// NB: pid contains the process ID of the child process
if p.use_stdio_ctl {
p.stdio_fd[0] = pipeset[1] // store the write end of child's in
p.stdio_fd[1] = pipeset[2] // store the read end of child's out
p.stdio_fd[2] = pipeset[4] // store the read end of child's err
// close the rest of the pipe fds, the parent does not need them
fd_close(pipeset[0])
fd_close(pipeset[3])
fd_close(pipeset[5])
}
return pid
}
//
// Here, we are in the child process.
// It still shares file descriptors with the parent process,
// but it is otherwise independant and can do stuff *without*
// affecting the parent process.
//
if p.use_pgroup {
C.setpgid(0, 0)
}
if p.use_stdio_ctl {
// Redirect the child standart in/out/err to the pipes that
// were created in the parent.
// Close the parent's pipe fds, the child do not need them:
fd_close(pipeset[1])
fd_close(pipeset[2])
fd_close(pipeset[4])
// redirect the pipe fds to the child's in/out/err fds:
C.dup2(pipeset[0], 0)
C.dup2(pipeset[3], 1)
C.dup2(pipeset[5], 2)
// close the pipe fdsx after the redirection
fd_close(pipeset[0])
fd_close(pipeset[3])
fd_close(pipeset[5])
}
execve(p.filename, p.args, p.env) or {
eprintln(err)
exit(1)
}
return 0
}
fn (mut p Process) unix_stop_process() {
C.kill(p.pid, C.SIGSTOP)
}
fn (mut p Process) unix_resume_process() {
C.kill(p.pid, C.SIGCONT)
}
fn (mut p Process) unix_kill_process() {
C.kill(p.pid, C.SIGKILL)
}
fn (mut p Process) unix_kill_pgroup() {
C.kill(-p.pid, C.SIGKILL)
}
fn (mut p Process) unix_wait() {
cstatus := 0
ret := C.waitpid(p.pid, &cstatus, 0)
if ret == -1 {
p.err = posix_get_error_msg(C.errno)
return
}
pret, is_signaled := posix_wait4_to_exit_status(cstatus)
if is_signaled {
p.status = .aborted
p.err = 'Terminated by signal ${ret:2d} (${sigint_to_signal_name(pret)})'
} else {
p.status = .exited
}
p.code = pret
}
fn (mut p Process) unix_is_alive() bool {
cstatus := 0
ret := C.waitpid(p.pid, &cstatus, C.WNOHANG)
if ret == -1 {
p.err = posix_get_error_msg(C.errno)
return false
}
if ret == 0 {
return true
}
pret, is_signaled := posix_wait4_to_exit_status(cstatus)
if is_signaled {
p.status = .aborted
p.err = 'Terminated by signal ${ret:2d} (${sigint_to_signal_name(pret)})'
} else {
p.status = .exited
}
p.code = pret
return false
}
// these are here to make v_win.c/v.c generation work in all cases:
fn (mut p Process) win_spawn_process() int {
return 0
}
fn (mut p Process) win_stop_process() {
}
fn (mut p Process) win_resume_process() {
}
fn (mut p Process) win_kill_process() {
}
fn (mut p Process) win_kill_pgroup() {
}
fn (mut p Process) win_wait() {
}
fn (mut p Process) win_is_alive() bool {
return false
}
fn (mut p Process) win_write_string(idx int, s string) {
}
fn (mut p Process) win_read_string(idx int, maxbytes int) (string, int) {
return '', 0
}
fn (mut p Process) win_slurp(idx int) string {
return ''
}
|