我有一个库的ctypes包装器。不幸的是,这个库不是100%可靠(偶尔会出现段错误等)。由于它的使用方式,我希望包装器能够在库崩溃时具有相当的弹性。
这样做的最佳方式似乎是分配一个过程并从孩子那里发回结果。我想沿着这些方向做点什么:
r, w = os.pipe()
pid = os.fork()
if pid == 0:
# child
result = ctypes_fn()
os.write(w, pickle.dumps(result))
os.close(w)
else:
# parent
os.waitpid(pid, 0)
result = os.read(r, 524288) # can be this big
os.close(r)
return pickle.loads(result)
但是,这并不是很有效。分叉的进程在写入时挂起。我想一次发送太多吗?这个问题有更简单的解决方案吗?
答案 0 :(得分:4)
可能你正在尝试编写的数据超出管道的数量,所以它会阻塞,直到有人出现并从那里读取一些信息。这种情况永远不会发生,因为唯一的读者是父进程,您似乎已经编写该进程以等待子进程在读取任何内容之前终止。这就是我们所说的死锁。
您可以考虑取出os.waitpid调用,看看会发生什么。另一种选择是看os.pipe是否有任何方法可以为它提供更大的缓冲区(我不知道你的环境可以说)。
答案 1 :(得分:2)
基本问题是管道有64kB的限制。一些可能的解决方案,从简单到复杂:
答案 2 :(得分:0)
ted.dennison提到的死锁的一个解决方案是以下伪代码:
#parent
while waitpid(pid, WNOHANG) == (0, 0):
result = os.read(r, 1024)
#sleep for a short time
#at this point the child process has ended
#and you need the last bit of data from the pipe
result = os.read(r, 1024)
os.close(r)
使用WNOHANG选项的Waitpid会导致waitpid在子进程尚未退出时立即返回。在这种情况下,它返回(0,0)。您需要确保不像上面的代码那样每次都通过循环覆盖结果变量。