golang:如何调试可能的竞争条件

时间:2017-01-12 13:52:45

标签: go race-condition

我在go中编写了一个日志收集器程序,它运行了一堆goroutines,如下所示:

  1. 例程A运行HTTP服务器,允许用户查看日志信息
  2. 例程B运行UDP服务器,允许从LAN发送日志消息
  3. 例程C运行一个计时器,它定期从内部HTTP文件服务器(不是程序的一部分)查询/下载压缩日志存档
  4. 例行程序B& C都将已处理的消息发送到频道
  5. 例程D使用select语句运行for {}循环,该语句从Channel接收消息并将其刷新到磁盘
  6. 还有一些其他的例程,例如扫描例程D生成的日志档案以创建SQLite索引等的例程。
  7. 该程序存在一个问题,即运行几个小时后,日志查看器http服务器仍能正常运行,但UDP或文件服务器例程中没有任何消息。我知道从各种渠道发送无休止的日志消息,如果我重新启动程序,它会再次开始处理传入的日志。

    我在编译器中添加了-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()
        }
    }
    

1 个答案:

答案 0 :(得分:0)

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

{{1}}

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

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

{{1}}