【发布时间】:2014-06-01 20:09:00
【问题描述】:
我使用 Flask 编写了一个 Python 应用程序,它提供了一个简单的网站,我可以使用它在我的 Raspberry Pi(微型计算机)上开始播放流视频。从本质上讲,该应用程序允许将我的手机或平板电脑用作遥控器。
我在 Mac OS 上测试了该应用程序,它运行良好。将其部署到 Raspberry Pi(安装了 Debian 的 Raspbian 变体)后,它可以很好地为网站提供服务,并且开始播放也可以按预期工作。但是,停止播放失败。
相关代码托管在这里:https://github.com/lcvisser/mlbviewer-remote/blob/master/remote/mlbviewer-remote.py
子进程是这样启动的:
cmd = 'python2.7 mlbplay.py v=%s j=%s/%s/%s i=t1' % (team, mm, dd, yy)
player = subprocess.Popen(cmd, shell=True, bufsize=-1, cwd=sys.argv[1])
这很好用。
子进程应该在此之后停止:
player.send_signal(signal.SIGINT)
player.communicate()
这确实在 Mac OS 上工作,但在 Raspberry Pi 上不工作:应用程序挂起,直到子进程(以 cmd 启动)完成本身。似乎SIGINT 没有被子进程发送或接收。
有什么想法吗?
(我也在这里发布了这个问题:https://unix.stackexchange.com/questions/133946/application-becomes-non-responsive-to-requests-on-raspberry-pi,因为我不知道这是操作系统问题还是 Python/Flask 相关问题。)
更新:
按照下面 Jan Vlcinsky 的建议尝试使用 player.communicate()(在最终看到警告 here 之后)没有帮助。
我正在考虑使用 Jan Vlcinsky 提出的解决方案,但如果 Flask 甚至没有收到请求,我认为这不会收到问题。
更新 2: 昨天晚上,我很幸运地遇到了能够准确指出问题的情况。用相关代码更新了问题。
我觉得 Jan Vlcinsky 的解决方案只是将问题转移到另一个应用程序,这将使 Flask 应用程序保持响应,但会让新应用程序挂起。
更新 3: 我编辑了问题的原始部分以删除我现在知道不相关的内容。
更新 4:在@shavenwarthog 的 cmets 之后,以下信息可能非常相关:
在 Mac 上,mlbplay.py 会这样启动:
rmtpdump <some_options_and_url> | mplayer -
当发送SIGINT 到mlbplay.py 时,它会终止这个管道命令创建的进程组(如果我understood 正确的话)。
在树莓派上,我用的是omxplayer,但是为了避免修改mlbplay.py(不是我的)的代码,我做了一个叫mplayer的脚本,内容如下:
#!/bin/bash
MLBTV_PIPE=mlbpipe
if [ ! -p $MLBTV_PIPE ]
then
mkfifo $MLBTV_PIPE
fi
cat <&0 > $MLBTV_PIPE | omxplayer -o hdmi $MLBTV_PIPE
我现在猜测最后一行启动了一个新进程组,该进程组没有被SIGINT 信号终止,从而使我的应用程序挂起。如果是这样,我应该以某种方式获取该组的进程组 ID,以便能够正确终止它。有人可以确认吗?
更新 5: omxplayer 确实处理 SIGINT:
https://github.com/popcornmix/omxplayer/blob/master/omxplayer.cpp#L131
更新 6: 事实证明,我的 SIGINT 不知何故在命令链的某处转换为 SIGTERM。 omxplayer 没有正确处理 SIGTERM,这似乎是事情一直挂起的问题。我通过实现一个 shell 脚本来解决这个问题,该脚本管理信号并将它们转换为适当的 omxplayer 命令(有点像 Jan 建议的蹩脚版本)。
解决方案:问题出在player.send_signal()。该信号未在命令链中正确处理,导致父应用程序挂起。解决方案是为不能很好地处理信号的命令实现包装器。
另外:使用Popen(cmd.split())而不是使用shell=True。这在发送信号时效果更好!
【问题讨论】:
-
你能分享一些代码吗?我会对您的 Flask 代码感兴趣(理想情况下是展示问题的完整工作示例,但至少是
subprocess.Popen的一部分)。 -
完整代码托管在这里:github.com/lcvisser/mlbviewer-remote/blob/master/remote/… 子进程在第 142 行开始,在第 163 行停止
标签: python linux raspberry-pi