我正在开发一个Go程序,它在并发循环中使用syscall.RawSyscall(syscall.SYS_FORK)
创建子进程.每个子进程需要执行一个应用了特定seccomp和rlimit限制的命令(/bin/ls
).父进程应该等待所有子进程使用syscall.Wait4
完成.然而,我遇到了一个问题,程序卡在syscall.Wait4(int(r1), nil, 0, nil)
.下面是代码的相关部分:
package main
import (
"fmt"
"os"
"os/exec"
"runtime"
"sync"
"syscall"
)
const n = 100
func main() {
var wg sync.WaitGroup
wg.Add(n)
for _ = range n {
go func() {
r1, _, err := syscall.RawSyscall(syscall.SYS_FORK, 0, 0, 0)
if err != 0 {
println("Error: ", err)
panic(err)
}
if r1 == 0 {
// Apply seccomp and rlimit restrictions here
cmd := exec.Command("/bin/ls", "ls")
cmd.Run()
os.Exit(0)
} else {
fmt.Println(int(r1))
syscall.Wait4(int(r1), nil, 0, nil)
wg.Done()
}
}()
}
wg.Wait()
fmt.Println("Done")
}
如果我删除syscall.Wait4
行,程序就不会再卡住了,但它也不会等待所有的子程序完成,这不是我想要的行为.我需要确保父进程等待所有子进程完成,并确保seccomp和rlimit限制正确应用于每个子进程.
我使用ChatGPT来帮助我生成C++版本,它做了同样的事情,它的工作和预期的一样.下面是我用来测试的C++代码.
#include <iostream>
#include <sys/wait.h>
#include <unistd.h>
#include <vector>
#include <thread>
const int n = 100;
void forkAndExec() {
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
} else if (pid == 0) {
// Child process
execl("/bin/ls", "ls", nullptr);
// If execl is successful, this line won't be executed
perror("execl");
exit(EXIT_FAILURE);
} else {
// Parent process
std::cout << "Child PID: " << pid << std::endl;
int status;
waitpid(pid, &status, 0);
}
}
int main() {
std::vector<std::thread> threads;
for (int i = 0; i < n; ++i) {
threads.emplace_back(forkAndExec);
}
for (auto &t : threads) {
t.join();
}
std::cout << "Done" << std::endl;
return 0;
}
有谁能帮我理解为什么程序卡在syscall.Wait4
,以及如何修复它,使父进程等待所有子进程完成后才退出?此外,对于正确地将seccomp和rlimit限制应用到子进程,我们将非常感激.
操作系统:Debian 12
内核版本:6.1.0—18—amd64
试过runtime.Gosched()
.不走运我还试图限制并发进程,它可以产生和使数字低于CPU核心我有.它确实有一点帮助,但有时我还是会再次遇到它.