gpt4 book ai didi

戈朗 : how to debug possible race condition

转载 作者:IT王子 更新时间:2023-10-29 02:22:30 25 4
gpt4 key购买 nike

我用go写了一个日志收集程序,它运行了一堆goroutines如下:

  1. 例程A运行HTTP服务器,允许用户查看日志信息
  2. 例程 B 运行 UDP 服务器,允许从 LAN 向其发送日志消息
  3. 例程 C 运行一个计时器,它定期从内部 HTTP 文件服务器(不是程序的一部分)查询/下载压缩日志存档
  4. 例程 B 和 C 都将处理过的消息发送到 Channel
  5. 例程 D 运行一个带有 select 语句的 for {} 循环,该语句从 Channel 接收消息并将其刷新到磁盘
  6. 还有一些其他的 go 例程,例如扫描例程 D 生成的日志存档以创建 SQLite 索引等的例程。

程序有一个问题,运行几个小时后,日志查看器 http 服务器仍然运行良好,但没有来自 UDP 或文件服务器例程的消息。我知道有无穷无尽的日志消息从各种 channel 发送,而且如果我重新启动程序,它会再次开始处理传入的日志。

我在编译器中添加了-race,它确实找到了一些有问题的代码,我修复了这些代码,但问题仍然存在。更重要的是,尽管存在不合理的问题,但无论是否存在不合理的代码,在我们的生产服务器上运行的旧版本代码都运行良好。

我的问题是,我怎样才能继续查明问题所在。以下是我的日志处理例程中的关键循环:

for {
select {
case msg := <-logCh:
logque.Cache(msg)
case <-time.After(time.Second):
}
if time.Since(lastFlush) >= 3 * time.Second {
logque.Flush()
lastFlush = time.Now()
}
}

最佳答案

我终于找到了造成阻塞的代码。在以下代码中:

for {
select {
case msg := <-logCh:
logque.Cache(msg)
case <-time.After(time.Second):
}
if time.Since(lastFlush) >= 3 * time.Second {
logque.Flush()
lastFlush = time.Now()
}
}

在 logque.Flush() 内部有一些代码生成日志消息,这些消息又写入 channel ,最终导致 channel 的缓冲区被填满。这仅在我打开 Debug模式时发生,生产代码不会在 Flush() 方法中执行此操作。

为了回答我自己的问题,我用来确定问题的方法非常简单:

if len(logch) >= LOG_CHANNEL_CAP {
//drop the message or store it into
//secondary buffer...
return
}
logch <- msg

关于戈朗 : how to debug possible race condition,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41614924/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com