【问题标题】:Writing a typed array to a subprocess stdin isn't working correctly将类型化数组写入子进程标准输入无法正常工作
【发布时间】:2018-11-27 08:01:03
【问题描述】:

我正在向子进程的标准输入发送一些数据。数据来自类型化数组。如果类型化数组中的数据发生更改,则发送到子进程的数据将被截断。我有一个小例子来说明这个问题。

Subprocess 是一个简单的 C++ 应用程序。从标准输入读取所有数据并将读取的字节数输出到标准输出。 (C++ App使用x86_64-w64-mingw32-g++ test.cpp编译) c++子进程代码:

#include <iostream>
#include <limits>

int main(int argc, char **args) {
  std::cin.ignore(std::numeric_limits<std::streamsize>::max());
  std::cout << std::cin.gcount() << std::flush;
  return 0;
}

nodejs 应用程序将调用循环 exe。将 128 字节的数据传递给标准输入并检查响应(来自子进程的标准输出)是否为字符串“128”。 nodejs App代码:

const execFile = require('child_process').execFile;

var data = new Float64Array(16);

var generateError = true;
generateError && setInterval(_ => {
  for (var i = 0; i < 16; i++) {
    data[i] = Math.random();
  }
}, 1);

setInterval(_ => {
  var subproc = execFile('a.exe', [ '-c' ], (error, stdout, stderr) => {
    if (stdout.trim() !== '128' || error) {
      console.log('ERR: ' + stdout);
    } else {
      console.log('OK');
    }
  });
  subproc.stdin.write(Buffer.from(data.buffer)) || console.log('Use drain'); // Write Binary Data (128Byte)
  subproc.stdin.end();
}, 100);

这给了我一些输出,例如:

OK
OK
OK
OK
OK
OK
ERR: 69
ERR: 114
OK
OK
OK
ERR: 41

是什么让我发疯:

  • 当我将 generateError 设置为 false 时,一切正常。
  • 当我使用“wc.exe -c”(来自 cgywin 的字/字节计数工具)时,一切都按预期工作,即使 generateError 设置为 true。

所以问题:怎么了? C++代码?节点代码? 传递给subproc.stdin.write之后是不是就不能改缓冲区了?如果不允许:为什么变体与 wc.exe 一起使用?

【问题讨论】:

  • 我对JS不熟悉,但是你的代码是否会为你运行的每个子进程生成一组新的数据?
  • JS 代码每 1ms 改变一次 data Array 的值(该数组应该一直是 16x8Bytes 长)。每 100 毫秒启动一个新的子进程(异步),并将数据数组发送到子进程。
  • Longshot:由于 Windows 和 cin 是文本模式流,所有位设置的字节都被解释为文件结尾。
  • @molbdnilo 从 C++ 的角度来看?从 nodejs 的角度来看?

标签: c++ node.js stream stdout stdin


【解决方案1】:

在 Windows 下有不同类型的流:二进制流和某些类型的文本流。将c++ App的输入流改为二进制流即可解决问题。 (我猜 wc.exe 会将输入流用作二进制流。这可以解释为什么 wc.exe 的变体可以工作):

#include <iostream>
#include <limits>

#include <fcntl.h>
#include <io.h>
int main(int argc, char **args) {
  _setmode(_fileno(stdin), _O_BINARY);

  std::cin.ignore(std::numeric_limits<std::streamsize>::max());
  std::cout << std::cin.gcount() << std::flush;
  return 0;
}

另见Read binary data from std::cin

【讨论】:

    猜你喜欢
    • 2018-12-14
    • 2013-06-24
    • 1970-01-01
    • 1970-01-01
    • 2013-08-17
    • 1970-01-01
    • 2012-10-25
    • 2014-10-29
    • 2012-01-18
    相关资源
    最近更新 更多