如何调试奇怪的线程打开 fifo 问题?

发布于 2024-07-14 23:19:39 字数 928 浏览 11 评论 0原文

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

在大多数情况下,它们工作得很好,但有时,由于某种原因,客户端会收到重复记录。 从日志来看,管道似乎没有正确关闭,并且缓存是剩余的,因此下次服务时,先前的和当前的都会发送到客户端。 问题是在尝试重现时它并不经常发生,不幸的是,我无法重现一次。

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

Web 服务器:(webserver.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,

那么究竟发生了什么导致了 dup? 如何触发呢? 当前的修复程序我取消链接管道文件并每次重新创建它以避免任何剩余,但我不知道这是否是正确的解决方案。

A web service is configured to expose some of its data when receiving a USR1 signal. The signal will be sent by a xinetd server when it receives a request from a remote client, e.g. nc myserver 50666. When the web server receives USR1 signal, it opens a dedicated fifo pipe, writes its data to the pipe, and then close the pipe. In the meantime, the xinetd server reads the pipe and feeds to the remote client.

In most of times, they work nicely but occasionally, for some reason, the client will receive dup records. From the log, it seems like the pipe did not get closed properly and the cache is leftover, so when next time it serves, both previous and current are sent to the client. The problem is its not constantly happening when trying to reproduce, unluckily, I wasn't able to reproduce once.

The following are the simple snippets to demonstrate the process:

The web server: (webserver.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()

The xinetd.d server: (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,

So what exactly happened to cause the dup? How to trigger it? The current fix I unlink the pipe file and recreate it every time to avoid any leftovers but I don't know if that's a proper solution.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

喜你已久 2024-07-21 23:19:39

如果您同时运行 splitter.py 的两个副本,则会出现麻烦,并且几乎任何发生在您身上的事情都是合法的。 尝试向 webserver.py 添加进程 id 值,即:

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

这可能很有启发。

If you get two copies of splitter.py running at the same time, there will be trouble and almost anything that happens to you is legal. Try adding a process id value to webserver.py, ie:

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

That might be illuminating.

和我恋爱吧 2024-07-21 23:19:39

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

如果可能的话,我建议不要使用信号。 它们在 C 语言中已经足够复杂了,更不用说在上面添加了 python 自己的特性。

There isn't enough to debug here. You don't show how the server handles signals, or opens the pipe.

If at all possible I would recommend not using signals. They're hairy enough in C, nevermind with python's own peculiarities added on top.

万劫不复 2024-07-21 23:19:39

所以真正的问题是存在多个客户端。 该服务器已被其他未知客户端查询/滥用,这些客户端最初并未与客户达成一致,并且肯定会在当前设计下崩溃。 已部署修复程序来解决该问题。 所以安迪的怀疑是对的。 多谢你们!

So the real problem is that there are multiple clients exist. The server has been queried/abused from other unknown clients which weren't initially being agreed with customers and sure it will break under the current design. A fix has been deployed to address the issue. So Andy's suspicion is right. Thanks guys!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文