我们最近在我们的项目上遇到了一个问题,试图将子过程管道作为整个base64编码的图片(大约355K)传递到其父流程:但是图片似乎被随机截断了,我们仍然没有得到这种行为,也没有找到解决方案。
我们找到了一种解决方法,可以通过基于tempfile的通信来传输这些图片,但是我们仍然想了解有关这些进程间通信限制的问题。
这是我们成功产生的最接近的最小和可复制示例,突出了此行为,我们有一个python脚本试图从节点子流程中检索数据,该节点子流程会生成要检索的数据。但是父进程能够获取的数据长度似乎是不确定的。
本示例测试请求的数据长度和实际检索的长度之间的相等性。
#!/usr/bin/env python3
import base64
import sys
import json
import subprocess
def test(l, executable):
process = subprocess.Popen(
executable,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
stdout, stderr = process.communicate(input=json.dumps(l).encode())
exit_code = process.returncode
if exit_code != 0:
raise RuntimeError("fail : " + str(stderr))
result = base64.b64decode(stdout.decode("utf-8"))
assert len(result) == l, f"{len(result)} != {l}"
print(f"Success: {len(result)} == {l}")
if __name__ == "__main__":
l = int(sys.argv[1]) if len(sys.argv) > 1 else 355000
try:
test(l, ["./test.js"])
except AssertionError as e:
print("fail :", e)
#!/usr/bin/env node
const http = require("http");
const serveHandler = require("serve-handler");
const btoa = require("btoa");
const EXIT_CODE_SUCCESS = 0;
const EXIT_CODE_ERROR = 4;
async function getDataFromStdin() {
return new Promise((resolve, reject) => {
let receivedData = '';
process.stdin.on("data", chunk => {
receivedData += chunk.toString();
});
process.stdin.on("end", () => {
result = resolve(JSON.parse(receivedData));
return result;
});
})
}
async function main(){
const len = await getDataFromStdin();
const base64 = btoa("0".repeat(Number(len)));
process.stdout.write(base64);
}
let errorCode = EXIT_CODE_SUCCESS;
main()
.catch(err => {
console.error(err);
errorCode = EXIT_CODE_ERROR;
}).finally(() => {
process.exit(errorCode);
});
vagrant@sc-dev-machine:/home/vagrant $ ./test.py 1
Success: 1 == 1
vagrant@sc-dev-machine:/home/vagrant $ ./test.py 1000
Success: 1000 == 1000
vagrant@sc-dev-machine:/home/vagrant $ ./test.py 30000
Success: 30000 == 30000
vagrant@sc-dev-machine:/home/vagrant $ ./test.py 60000
fail : 49152 != 60000
vagrant@sc-dev-machine:/home/vagrant $ ./test.py 60000
Success: 60000 == 60000
vagrant@sc-dev-machine:/home/vagrant $ ./test.py 120000
fail : 49152 != 120000
vagrant@sc-dev-machine:/home/vagrant $ ./test.py 120000
fail : 98304 != 120000
vagrant@sc-dev-machine:/home/vagrant $
我们还尝试了subprocess.check_output()
基于解决方案的解决方案,但没有取得更好的结果。
这可能是什么解释?EOF在进程之间以及通过管道终止了数据块?缓冲(我们怀疑是原因)不能传输全部数据吗?
是否存在一种经过验证的方法来通过过程传输数据(例如文件或图片)而没有与长度相关的限制?
编辑:这也是有关环境的一些信息:
vagrant@sc-dev-machine:/home/vagrant $ uname -a
Linux sc-dev-machine 4.15.0-74-generic #84-Ubuntu SMP Thu Dec 19 08:06:28 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
vagrant@sc-dev-machine:/home/vagrant $ python3 --version
Python 3.6.8
问题出在您的JavaScript代码中,您可以在这里找到说明:
调用
process.exit()
将迫使进程尽快退出,即使仍有尚未完成的异步操作(包括对process.stdout
和的I / O操作)也尚未完成process.stderr
。
和:
在大多数情况下,实际上没有必要
process.exit()
显式调用。如果事件循环中没有其他待处理的工作,则Node.js进程将自行退出。process.exitCode
可以设置该属性,以告知进程正常退出时要使用哪个退出代码。
您是process.exit()
在调用process.stdout.write()
完成之前进行调用的(在POSIX上异步写入管道)。这将导致JS进程过早退出,并在写入所有数据之前中断写入。
如果您要设置错误代码,则应照常进行设置process.exitCode = errorCode
,并允许事件循环正常结束而无需调用process.exit()
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句