Tenho os dois programas simples a seguir.
Pai:
package main
import (
"fmt"
"syscall"
)
func main() {
attr := &syscall.ProcAttr{
Files: []uintptr{0, 1, 2},
Sys: &syscall.SysProcAttr{ // child in its own group
Setpgid: true,
Pgid: 0,
},
}
_, err := syscall.ForkExec("./child/child", []string{"child"}, attr)
if err != nil {
fmt.Println("Error:", err)
return
}
}
Criança:
package main
import (
"fmt"
"time"
)
func main() {
for {
fmt.Println("hi from child")
time.Sleep(time.Second * 5)
}
}
Saída do ps
:
yakog@yakog-computer:~/goprojects/parent$ ps -o pid,ppid,pgid,uid,wchan,stat,tt,command -t /dev/pts/19
PID PPID PGID UID WCHAN STAT TT COMMAND
1867701 1867320 1867701 1000 do_sel Ss+ pts/19 bash
1870508 2118 1870508 1000 ep_pol Sl pts/19 child
Quando pressiono CTRL-Z
ou CTRL-C
, não tem efeito algum. É exatamente o que eu esperava, já que o processo 1870508 não faz parte do trabalho de primeiro plano e CTRL-Z
/ CTRL-C
invoca kill -SIGTSTP -1867701
/ kill -SIGINT -1867701
. Portanto, 1870508 não recebe esses sinais.
Além disso, quando invoco kill -SIGINT 1870508
ou kill -SIGSTOP 1870508
, o processo é encerrado/suspenso. Ainda consigo entender. Embora 1870508 não faça parte do trabalho em primeiro plano, com kill
o comando enviamos "diretamente" o sinal para o processo .
No entanto, por que kill -SIGTSTP 1870508
não funciona? Após iniciar o ./parent
processo e chamar kill -SIGTSTP 1870508
o comando, literalmente nada acontece (o 1870508 ainda tem status R
/ S
e continua a imprimir no terminal). Não consigo entender por que ele não suspendeu o processo (o moveu para T
). Deve ser o mesmo que com -SIGINT
e -SIGSTOP
( nós enviamos "diretamente" -SIGTSTP para o processo ), no entanto, não tem efeito neste caso.
O estranho é que se alterarmos o código pai (código abaixo) e fizermos com que ele continue a execução após a criação do filho, ele kill -SIGTSTP 1870508
funcionará como deveria (o filho será suspenso).
package main
import (
"fmt"
"os/signal"
"syscall"
"time"
)
func main() {
attr := &syscall.ProcAttr{
Files: []uintptr{0, 1, 2},
Sys: &syscall.SysProcAttr{ // child in its own group
Setpgid: true,
Pgid: 0,
},
}
_, err := syscall.ForkExec("./child/child", []string{"child"}, attr)
signal.Ignore(syscall.SIGTSTP)
if err != nil {
fmt.Println("Error:", err)
return
}
for {
fmt.Println("hi from parent")
time.Sleep(time.Second * 7)
}
}
Além disso, quando eu invoco kill -SIGSTOP 1870508
(movo o processo para T
o estado) e então invoco, kill -SIGINT 1870508
o processo não é encerrado... Por quê?