kernelsauce / turbo

Turbo is a framework built for LuaJIT 2 to simplify the task of building fast and scalable network applications. It uses a event-driven, non-blocking, no thread design to deliver excellent performance and minimal footprint to high-load applications while also providing excellent support for embedded uses.
http://turbo.readthedocs.io/
Apache License 2.0
525 stars 84 forks source link

iostream: Fix initial read for FFI sockets #329

Closed mniestroj closed 6 years ago

mniestroj commented 6 years ago

When running httpserver.lua example and executing 'nmap localhost -p 8888' command we get error listed below. After that it is no longer possible to handle HTTP requests.

[mniestroj@gm examples]$ luajit httpserver.lua [E 2018/01/26 17:00:56] [ioloop.lua] Error in IOLoop handler. ▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼ /usr/local/share/lua/5.1/turbo/iostream.lua:650: Error when reading from socket 5. Errno: 104. Connection reset by peer stack traceback: [C]: in function 'error' /usr/local/share/lua/5.1/turbo/iostream.lua:650: in function '_read_from_socket' /usr/local/share/lua/5.1/turbo/iostream.lua:725: in function '_read_to_buffer' /usr/local/share/lua/5.1/turbo/iostream.lua:467: in function '_initial_read' /usr/local/share/lua/5.1/turbo/iostream.lua:200: in function 'read_until' /usr/local/share/lua/5.1/turbo/httpserver.lua:130: in function 'initialize' ...share/lua/5.1/turbo/3rdparty/middleclass/middleclass.lua:90: in function 'HTTPConnection' /usr/local/share/lua/5.1/turbo/httpserver.lua:101: in function 'handle_stream' /usr/local/share/lua/5.1/turbo/tcpserver.lua:213: in function </usr/local/share/lua/5.1/turbo/tcpserver.lua:200> /usr/local/share/lua/5.1/turbo/sockutil.lua:244: in function </usr/local/share/lua/5.1/turbo/sockutil.lua:204> [C]: in function 'xpcall' /usr/local/share/lua/5.1/turbo/ioloop.lua:546: in function '_run_handler' /usr/local/share/lua/5.1/turbo/ioloop.lua:454: in function '_event_poll' /usr/local/share/lua/5.1/turbo/ioloop.lua:443: in function 'start' httpserver.lua:43: in main chunk [C]: at 0x00404680 ▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲

This bug is only reproducible when socket is closed just after opening, as it is in case of nmap command above. The root cause is that we try to read from socket just after opening it. We get an ECONNRESET error, because there socket was closed immediately.

Watch for ECONNRESET error during read, so we make sure immediately closed connection are handled properly.

mniestroj commented 6 years ago

Hi, I wonder if we need to have 'initial read'? Removing initial read could also be a solution. What do you think about that?

kernelsauce commented 6 years ago

Hi. The the intention with the initial read is to empty buffer before going for another iteration in the IO loop for the same socket. It is not needed of course, but its a optimization that is nice to have there.

kernelsauce commented 6 years ago

Thanks for your contribution, I merged it in and made a new release by the way.