Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

common.socket->onData error #17

Closed
nagisa3000 opened this issue Jul 4, 2017 · 12 comments
Closed

common.socket->onData error #17

nagisa3000 opened this issue Jul 4, 2017 · 12 comments

Comments

@nagisa3000
Copy link

用MEM检查内存的时候,浏览器会卡在“Memory Stream 准备完毕,即将开启子进程进行流式读取,此过程较慢,请耐心等待...”,cmd报错common.socket->onData error: TypeError: Cannot read property 'on' of null。
请问这个问题该怎么排查。

@hyj1991
Copy link
Owner

hyj1991 commented Jul 4, 2017

@nagisa3000 我看看本地能不能复现,你用的机器是 Windows 还是 Mac / Linux 呢,而且这个是偶尔会还是很大概率能复现的呢?我在本地似乎没办法复现这个错误

感谢提供错误信息,如果有更多的错误信息可以在这里回复~

@nagisa3000
Copy link
Author

@hyj1991 我用的是64位Win7 在我的机子上是必现的错误。

@hyj1991
Copy link
Owner

hyj1991 commented Jul 4, 2017

@nagisa3000 我刚才找了台 Win7 64 位的测试了一下,跑了几次 MEM 检测都没有问题哇

这样子,你打开 node_modules/easy-monitor/src_logic/common/common.socket.js 文件,修改此文件的 105 行,将原本的:

returnMsg.then(r => r && common.socket.sendMessage(socket, r)).catch(e => dbl.error(`common.socket->onData error: ${e}`));

改为:

returnMsg.then(r => r && common.socket.sendMessage(socket, r)).catch(e => dbl.error(`common.socket->onData error: ${e.stack}`));

然后重启你的项目,再测试一遍,把得到的错误详细栈信息复制到这边,我看下

@hyj1991 hyj1991 added the bug label Jul 4, 2017
@nagisa3000
Copy link
Author

[Easy-Monitor: dashboard <7664>] http_server start at 12333...
[Easy-Monitor: dashboard <7664>] tcp_server start at 26666...
[2017-07-04 15:21:59.147] [INFO] console - [Easy-Monitor: embrace <7888>] connect to 127.0.0.1:26666 success...
[2017-07-04 15:22:05.689] [INFO] console - [Easy-Monitor: embrace <7888>] common.socket->onData error: TypeError: Cannot read property 'on' of null
at ExportStream.Readable.pipe (_stream_readable.js:507:7)
at ChildProcess._innerSend [as innerSend] (E:\dev_server\node_modules\easy-monitor\src_logic\common\common.calculate.js:17:17)
at _start (E:\dev_server\node_modules\easy-monitor\src_logic\embrace\controller\tcp.profiler.js:74:21)
at next (native)
at onFulfilled (E:\dev_server\node_modules\co\index.js:65:19)
at process._tickDomainCallback (internal/process/next_tick.js:129:7)


@hyj1991 错误信息如上 顺带我用的node版本是6.2.0

@hyj1991
Copy link
Owner

hyj1991 commented Jul 4, 2017

@nagisa3000 好的,这是比较关键的信息,我先下载 Node 6.2 看看能不能复现

@hyj1991
Copy link
Owner

hyj1991 commented Jul 4, 2017

@nagisa3000
找到原因了,是 Node 核心模块 child_process.js 升级过程中对于 fork 子进程时传入的 stdio 参数版本没有向下兼容导致的:

  • Node v6.4.0 之前,不支持在 fork 子进程时配置 stdio 参数

Node v6.4.0 之前的 lib/child_process.js 文件相关原始代码如下:

options.stdio = options.silent ? ['pipe', 'pipe', 'pipe', 'ipc'] :
      [0, 1, 2, 'ipc'];

从 v6.4.0 开始后支持配置 stdio 参数,lib/child_process.js 文件相关代码更改为:

if (!Array.isArray(options.stdio)) {
    // Leave stdin open for the IPC channel. stdout and stderr should be the
    // same as the parent's if silent isn't set.
    options.stdio = options.silent ? ['pipe', 'pipe', 'pipe', 'ipc'] :
        [0, 1, 2, 'ipc'];
  } else if (options.stdio.indexOf('ipc') === -1) {
    throw new TypeError('Forked processes must have an IPC channel');
  }

而在 Easy-Monitor v2.1.2 中开启子进程进行负载的逻辑计算,因为只使用到了 stdin 流传输数据,所以仅设置了 stdin 流为管道类型:

function fork(cpath, params) {
        //取出公共部分
        const config = this.config;
        const common = this.common;
        const dbl = this.dbl;

        //fork 进程,stdio 设置子进程的 stdin 为 pipe 备用传输数据,其余默认
        params = typeof params === 'string' && params || params && JSON.stringify(params) || '';
        const ps = cp.fork(cpath, [params], { stdio: ['pipe', 1, 2, 'ipc'], silent: false, execArgv: [] });
        //设置子进程内部方法
        ps.innerSend = _innerSend;

        return ps;
    }

这部分代码显然在 Node v6.4.0 之前时 stdio 参数设置无法生效,所以会报这个错误。

临时解决方案

更改 node_modules/easy-monitor/src_logic/common/common.calculate.js38 行,将原本的:

const ps = cp.fork(cpath, [params], { stdio: ['pipe', 1, 2, 'ipc'], silent: false, execArgv: [] });

更改为:

const ps = cp.fork(cpath, [params], { stdio: ['pipe', 1, 2, 'ipc'], silent: true, execArgv: [] });

这样可以临时解决这个问题,我再看看怎么做更加理想的兼容方式,预计下个版本合并解决这个问题。

参考列表:
CHANGELOG_V6.md#6.4.0
child_process: support stdio option in fork()

@nagisa3000
Copy link
Author

@hyj1991 修改后可以正常执行了。十分感谢~

@hyj1991
Copy link
Owner

hyj1991 commented Jul 4, 2017

@nagisa3000 好的,不客气,感谢提供有用的信息反馈

@hyj1991
Copy link
Owner

hyj1991 commented Jul 4, 2017

@nagisa3000

Hi,这个问题已经修复: commit#f00c00421cf5bb6421730fcfd41a1cbf443a94c4

下个版本合并

@nagisa3000
Copy link
Author

@hyj1991 嗯嗯好的

@hyj1991
Copy link
Owner

hyj1991 commented Jul 6, 2017 via email

@nagisa3000
Copy link
Author

@hyj1991 嗯嗯 确实太古老了

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants