Permalink
Browse files

bugfix: data might be accidentally read into the lua space on idle so…

…ckets when the last operation is a read operation *and* a read event suddenly arrives for edge-triggered event models. the same might also apply to write operations too. bugfix: invalid reads might happen in the reading iterators returned by the receiveuntil() method which could lead to segfaults.
  • Loading branch information...
1 parent 1bce885 commit 9026d59fd453aaf9b1b20fccb12d98080ecb1b54 @agentzh agentzh committed Feb 18, 2012
Showing with 96 additions and 4 deletions.
  1. +8 −2 src/ngx_http_lua_socket.c
  2. +1 −1 t/058-tcp-socket.t
  3. +87 −1 t/066-socket-receiveuntil.t
View
@@ -1839,6 +1839,11 @@ ngx_http_lua_socket_handle_success(ngx_http_request_t *r,
{
ngx_http_lua_ctx_t *ctx;
+#if 1
+ u->read_event_handler = ngx_http_lua_socket_dummy_handler;
+ u->write_event_handler = ngx_http_lua_socket_dummy_handler;
+#endif
+
#if 0
if (u->eof) {
ngx_http_lua_socket_finalize(r, u);
@@ -2430,7 +2435,7 @@ ngx_http_lua_socket_read_until(void *data, ssize_t bytes)
while (i < bytes) {
c = b->pos[i];
- dd("%d: read char %c, state: %d", i, c, state);
+ dd("%d: read char %d, state: %d", i, c, state);
if (c == pat[state]) {
i++;
@@ -2471,7 +2476,8 @@ ngx_http_lua_socket_read_until(void *data, ssize_t bytes)
matched = 0;
- if (cp->recovering) {
+ if (cp->recovering && state >= 2) {
+ dd("accessing state: %d, index: %d", state, state - 2);
for (edge = cp->recovering[state - 2]; edge; edge = edge->next) {
if (edge->chr == c) {
View
@@ -1763,7 +1763,7 @@ subrequest: 200, OK\r
local sock = ngx.socket.tcp()
local port = ngx.var.port
- sock:settimeout(300)
+ sock:settimeout(400)
local ok, err = sock:connect("127.0.0.1", port)
if not ok then
@@ -12,7 +12,7 @@ our $HtmlDir = html_dir;
$ENV{TEST_NGINX_CLIENT_PORT} ||= server_port();
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211;
-no_long_string();
+#no_long_string();
#no_diff();
#log_level 'warn';
@@ -999,3 +999,89 @@ close: nil closed
--- no_error_log
[error]
+
+
+=== TEST 15: read events come when socket is idle
+--- config
+ server_tokens off;
+ location /t {
+ set $port $TEST_NGINX_CLIENT_PORT;
+
+ content_by_lua '
+ local sock = ngx.socket.tcp()
+ local port = ngx.var.port
+
+ local ok, err = sock:connect("127.0.0.1", port)
+ if not ok then
+ ngx.say("failed to connect: ", err)
+ return
+ end
+
+ ngx.say("connected: ", ok)
+
+ local req = "GET /foo HTTP/1.1\\r\\nHost: localhost\\r\\nConnection: close\\r\\n\\r\\n"
+
+ local bytes, err = sock:send(req)
+ if not bytes then
+ ngx.say("failed to send request: ", err)
+ return
+ end
+ ngx.say("request sent: ", bytes)
+
+ local reader = sock:receiveuntil("foofoo\\r\\n")
+ local line, err, part = reader()
+ if line then
+ ngx.print("read: ", line)
+
+ else
+ ngx.say("failed to read a line: ", err, " [", part, "]")
+ end
+
+ ngx.location.capture("/sleep")
+
+ local data, err, part = sock:receive("*a")
+ if not data then
+ ngx.say("failed to read the 2nd part: ", err)
+ else
+ ngx.say("2nd part: [", data, "]")
+ end
+
+ ok, err = sock:close()
+ ngx.say("close: ", ok, " ", err)
+ ';
+ }
+
+ location /sleep {
+ echo_sleep 0.5;
+ more_clear_headers Date;
+ }
+
+ location /foo {
+ echo -n foofoo;
+ echo_flush;
+ echo_sleep 0.3;
+ echo -n barbar;
+ more_clear_headers Date;
+ }
+--- request
+GET /t
+--- response_body eval
+qq{connected: 1
+request sent: 57
+read: HTTP/1.1 200 OK\r
+Server: nginx\r
+Content-Type: text/plain\r
+Transfer-Encoding: chunked\r
+Connection: close\r
+\r
+6\r
+2nd part: [6\r
+barbar\r
+0\r
+\r
+]
+close: nil closed
+}
+--- no_error_log
+[error]
+

0 comments on commit 9026d59

Please sign in to comment.