Golang中goroutines导致程序崩溃(收到signal killed信号)
Golang中goroutines导致程序崩溃(收到signal killed信号) 我有一个应用程序会启动多个goroutine,如下所示:
func ExecProcess(cmdname string, params *[]string) {
cmd := exec.Command(cmdname, (*params)[0:]...)
if err := cmd.Start(); err != nil {
println(err.Error())
return
}
// Wait for the process to finish or kill it after a timeout (whichever happens first):
done := make(chan error, 1)
go func() {
done <- cmd.Wait()
}()
select {
case <-time.After(45 * time.Second):
if err := cmd.Process.Kill(); err != nil {
println("failed to kill process: " + err.Error())
}
println("process killed as timeout reached")
case err := <-done:
if err != nil {
println("process finished with error = " + err.Error())
}
}
}
在Linux系统下,我的应用程序被终止(信号终止)并显示以下消息: process finished with error = signal killed
你知道如何防止这种情况发生吗?
此致
更多关于Golang中goroutines导致程序崩溃(收到signal killed信号)的实战教程也可以访问 https://www.itying.com/category-94-b0.html
3 回复
这只是一个内存不足的问题
更多关于Golang中goroutines导致程序崩溃(收到signal killed信号)的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
你好,@Fookiwara,你是说运行你的 ExecProcess 函数的 Go 程序被终止了,还是你从 ExecProcess 中运行的程序被终止了?如果是后者,那么在我看来它似乎是被超时终止的。
问题分析:您的程序收到"signal killed"通常是因为系统资源不足(如内存不足)导致OOM Killer终止进程,或者是goroutine泄漏导致资源耗尽。在您的代码中,主要问题可能是:
- 未正确处理子进程的退出
- 未限制并发goroutine数量
- 未回收子进程资源
解决方案:
func ExecProcess(cmdname string, params []string) error {
cmd := exec.Command(cmdname, params...)
// 设置进程组ID以便正确杀死整个进程树
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
if err := cmd.Start(); err != nil {
return err
}
done := make(chan error, 1)
go func() {
done <- cmd.Wait()
}()
select {
case <-time.After(45 * time.Second):
// 杀死整个进程组
if err := syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL); err != nil {
return fmt.Errorf("failed to kill process: %v", err)
}
return fmt.Errorf("process killed as timeout reached")
case err := <-done:
return err
}
}
// 使用worker pool限制并发goroutine数量
type ProcessPool struct {
sem chan struct{}
}
func NewProcessPool(maxWorkers int) *ProcessPool {
return &ProcessPool{
sem: make(chan struct{}, maxWorkers),
}
}
func (p *ProcessPool) ExecProcess(cmdname string, params []string) error {
p.sem <- struct{}{}
defer func() { <-p.sem }()
return ExecProcess(cmdname, params)
}
// 使用示例
func main() {
pool := NewProcessPool(10) // 限制最多10个并发进程
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
err := pool.ExecProcess("sleep", []string{"10"})
if err != nil {
fmt.Printf("Process %d failed: %v\n", i, err)
}
}(i)
}
wg.Wait()
}
关键改进点:
- 使用
Setpgid创建进程组,确保能正确杀死整个进程树 - 使用worker pool模式限制并发goroutine数量
- 使用
sync.WaitGroup确保所有goroutine正确完成 - 改进错误处理,返回错误而不是直接打印
- 使用
SIGKILL确保进程被强制终止
这样可以避免资源泄漏和过度并发导致的系统资源耗尽问题。

