Results 20 issues of 淘小杰

记得刚刚开始学Node.js时自己尝试着写了一个简单的http服务器,跟以前接触过的php相比感觉更自由,编起码来也更爽了。但是某天发现稍微一个很小的错误就导致整个http进程挂掉了,顿时有种不靠谱的感觉啊,跟php比起来感觉Node.js容错能力确实弱了很多,起码一个php文件出错也不会导致所有的服务都挂掉。 后来接触到Node.js web开发框架后感觉也不是那么轻易就让整个进程都挂掉的,于是便想研究下Node.js究竟是如何来处理各种异常从而避免整个进程挂掉的。 当我们的程序运行在Node.js进程里不小心抛出一个异常时便会触发process对象的_fatalException方法,并将异常对象err传进去,_fatalException方法主要做以下一些处理: 当process对象上有绑定domain时便调用domain对象的_errorHandler方法来处理, ``` javascript if (process.domain && process.domain._errorHandler) caught = process.domain._errorHandler(er) ``` _errorHandler会返回一个布尔值来通知当前程序domain是否有对该异常进行处理,如果domain没有做处理,此时process对象便会触发一个绑定到process上的uncaughtException事件来处理该异常,并且同样会返回一个布尔值来通知当前程序是否有对异常进行处理。 ``` javascript if (!caught) caught = process.emit('uncaughtException', er); ``` 走到这个地步时如果异常还没被正常的处理那么此时process就有点不高兴了,既然你们都不处理那我就准备让你们全部挂掉吧!(确实太狠了点啊),这个时候悲剧即将发生。。。 ``` javascript if (!caught)...

## 背景 Node.js 内置的进程间通信使用非常简单,但也有一定的局限性,只能在父子进程间通信。下面是官方文档给的一个例子。 首先是父进程的 parent.js : ``` const cp = require('child_process'); const n = cp.fork(`${__dirname}/sub.js`); n.on('message', (m) => { console.log('PARENT got message:', m); }); n.send({ hello: 'world' }); ```...

## 背景 Node.js 社区近期在美国独立日周末的狂欢之时爆出漏洞 https://medium.com/@iojs/important-security-upgrades-for-node-js-and-io-js-8ac14ece5852 先给出一段会触发该漏洞的代码 ![http://img3.tbcdn.cn/L1/461/1/d5401fbf1e68213766c920c6ee0377ae18710276](http://img3.tbcdn.cn/L1/461/1/d5401fbf1e68213766c920c6ee0377ae18710276) 直接在v0.12.4版本的node上运行,立即crash。 ![http://gtms03.alicdn.com/tps/i3/TB1EwJ8IFXXXXXSaXXXbL4aIXXX-780-130.png](http://gtms03.alicdn.com/tps/i3/TB1EwJ8IFXXXXXSaXXXbL4aIXXX-780-130.png) 下面我们详细的分析下该漏洞的原理。 ## 调用栈 上面的代码构造了一个长度为1025的buffer,然后调用该buffer的toString方法解码成utf8字符,平时开发中再平常不过的调用了。但是为什么在这里会导致crash呢,和平时的写法到底有什么差别? 示例代码虽少,但是里面涉及到的各种调用可不少,从js到node中的c++,再到更底层的v8调用。大致过程如下图所示。 ![调用栈](http://gtms02.alicdn.com/tps/i2/TB11jB_IFXXXXbMXVXXnM9tRpXX-590-540.png) ### 关键调用 导致该漏洞产生的有几个比较关键的调用过程。 #### Utf8DecoderBase::Reset 每一个`Utf8DecoderBase`类实例化的对象都有一个私有的属性`buffer_`, ``` c++ private: uint16_t buffer_[kBufferSize]; ``` 其中utfDecoder的kBufferSize设置为512,buffer_用做存储解码后的utf8字符缓冲区。这里需要注意的是512不是字节数,而是字符数,有些utf8字符只需要一个这样的字符就能表示,有些则需要2个。示例代码中构造buffer用的微笑字符则需要2个这样的字符来表示,4个字节来存储。所以buffer_能存储的字节数是512*2=1024。 如果待解码的buffer长度不超过1024时,在buffer_中就能完全被解码完。解码到buffer_的字符通过调用`v8::internal::OS::MemCopy(data, buffer_,...

前几天nodejs发布了新版本4.0,其中涉及到一个更新比较多的模块,那就是下面要介绍的timer模块。 > timers: Improved timer performance from porting the 0.12 implementation, plus minor fixes (Jeremiah Senkpiel)#2540, (Julien Gilli)nodejs/node-v0.x-archive#8751nodejs/node-v0.x-archive#8905 之前也对timer模块有过比较多的研究,断断续续的看过这个模块在github上的一些改动,于是借着这次机会整理一下自己对timer模块的理解,和小伙伴们一起分享timer模块的优化过程。 ## 使用场景 也许你在使用nodejs开发项目时并没有使用到timer模块,诸如setTimeout以及setInterval和setImediate方法等等。但如果你开发的是web项目,那么你的项目中一定涉及到了timer模块。 细心的同学在平时的http接口开发调试中可能会注意到,每个http的request header里都有一个`Connection:keep-alive`标识,这是http/1.1开始引入的,表示客户端需要和服务端一直保持着tcp连接。当然了,这个连接不能就这么一直保持着,所以一般都会有一个超时时间,超过这个时间客户端还没有发送新的http请求,那么服务器就需要自动断开从而继续为其他客户端提供服务。 nodejs提供的http服务器便是采用timer模块来满足这种请求,每一个新的连接到来构造出一个socket对象,便会调用socket.setTimeout设置一个定时器用于超时后自动断开连接。 ## 设计 在nodejs开发的web项目中,timer模块的使用频率是非常高的,每一个新的连接到来都会设置它的超时时间,而且每个连接的超时时间都一样,在http server中默认是2 \*...

a simple timer based on kqueue and min binary heap ``` c #include #include #include #include #include #include #include #include #include //https://github.com/joyent/libuv/blob/master/src/heap-inl.h #include "heap-inl.h" #define container_of(ptr, type, member) \ ((type...

``` js Buffer(Array(258).join('😊')).slice(0,-3).toString(); ```

Node.js ``` js while(1){ var size = 1028; var buf = Buffer(size); for(var i=0;i

### uv_loop_t ``` js { data = 0x0000000000000000 active_handles = 2 handle_queue = ([0] = void * = 0x00000001000238a0, [1] = void * = 0x0000000100023bc8) active_reqs = ([0] = void...

It was ok in debug mode, but failed in release mode. ``` Failed to lookup symbol (dlsym(RTLD_DEFAULT, test_func): symbol not found) #0 DynamicLibrary.lookup (dart:ffi-patch/ffi_dynamic_library_patch.dart:33) ```

package:ffi