代码之家  ›  专栏  ›  技术社区  ›  jimx

如何调试一个奇怪的线程开放FIFO问题?

  •  0
  • jimx  · 技术社区  · 16 年前

    Web服务配置为在接收USR1信号时公开其部分数据。当xinetd服务器从远程客户端(如nc myserver 50666)收到请求时,该信号将由xinetd服务器发送。当Web服务器接收到USR1信号时,它打开一个专用的FIFO管道,将其数据写入管道,然后关闭管道。同时,xinetd服务器读取管道并向远程客户机提供数据。

    在大多数情况下,它们工作得很好,但有时出于某种原因,客户会收到DUP记录。从日志中可以看出,管道似乎没有正确关闭,缓存被遗留下来,所以下次使用时,前一个和当前的都会发送到客户机。问题是,当我试图繁殖的时候,它不会经常发生,不幸的是,我不能繁殖一次。

    以下是演示流程的简单片段:

    Web服务器:(web server.py)

    def SendStream(data, pipe):
      try:
        for i in data:
          pipe.write(i + '\n') 
          pipe.flush()
      finally:
          pipe.close()
    
    def Serve():
      threading.Thread(target=SendStream, args=(data, pipe)).start()
    

    xinetd.d服务器:(spitter.py)

    def Serve():
      if not os.path.exists(PIPE_FILE):
        os.mkfifo(PIPE_FILE)
      os.kill(server_pid, signal.SIGUSR1)
      for i in open(PIPE_FILE):
        print i,
    

    那么究竟是什么导致了这个骗局?如何触发?当前的修复方法是断开管道文件的链接,每次都重新创建它以避免任何遗留问题,但我不知道这是否是正确的解决方案。

    3 回复  |  直到 16 年前
        1
  •  0
  •   Andy    16 年前

    如果同时运行splitter.py的两个副本,就会出现问题,而且几乎所有发生在您身上的事情都是合法的。尝试将进程ID值添加到webserver.py,即:

    pipe.write(str(os.getpid())+i+'\n')

    这可能很有启发性。

        2
  •  0
  •   Rhamphoryncus    16 年前

    这里没有足够的调试。您不显示服务器如何处理信号,也不显示如何打开管道。

    如果可能的话,我建议不要使用信号。它们在C语言中已经足够多毛了,而不需要再加上python自己的特性。

        3
  •  0
  •   jimx    16 年前

    所以真正的问题是存在多个客户机。服务器已从其他未知客户机被查询/滥用,这些客户机最初没有与客户达成一致意见,并确保在当前设计下它将中断。已部署修复程序来解决此问题。所以安迪的怀疑是对的。谢谢大家!