On Wed, May 9, 2012 at 9:00 AM, Matthieu Tourne
<matthie...@gmail.com> wrote:
> I made some progress on adding the option { inclusive = true },
Yay!
> the code
> actually work but I'm having trouble reading the option table in C.
> (Should be pretty trivial but I'm not really experienced dealing with the
> Lua stack object)
> Any idea why this would cause a segfault later somewhere ?
> (see diff below)
>
I've applied your diff to my local checkout, and seen a lua assertion
failed due to this patch as seen in error.log:
nginx: lj_api.c:773: lua_rawgeti: Assertion `(((t)->it) == (~11u))' failed.
And gdb shows the backtrace for this abortion:
#0 0x00007f2001e4b3d5 in raise () from /lib64/libc.so.6
#1 0x00007f2001e4cbe0 in abort () from /lib64/libc.so.6
#2 0x00007f2001e44471 in __assert_fail () from /lib64/libc.so.6
#3 0x00007f200326267d in lua_rawgeti (L=0x404193c0, idx=<value
optimized out>, n=1) at lj_api.c:773
#4 0x00000000404193c0 in ?? ()
#5 0x00000000404193c0 in ?? ()
#6 0x00000000404193c0 in ?? ()
#7 0x000000000049e200 in ngx_http_lua_socket_receiveuntil_iterator (L=0x49e185)
at /home/agentz/git/lua-nginx-module/src/ngx_http_lua_socket.c:2258
According to ngx_http_lua_socket.c:2258, the upvalues for the iterator
seem to be screwed up.
And looking at your patch, it changes how the upvalue arrangement for
the iterator. See
lua_pushcclosure(L, ngx_http_lua_socket_receiveuntil_iterator, 3);
It assumes three upvalues on the stack:
1. at index 1: the cosocket object table
2. at index 2: the pattern string
3. at index -1 (or 3): the cp pointer
So when the user feeds the 3rd argument, it makes the cp pointer away
from the position 3. So we need to pop the 3rd option table as soon as
possible.
The following patch fixed this:
diff --git a/src/ngx_http_lua_socket.c b/src/ngx_http_lua_socket.c
index 27825fb..2c5a05a 100644
--- a/src/ngx_http_lua_socket.c
+++ b/src/ngx_http_lua_socket.c
@@ -2157,15 +2157,35 @@ ngx_http_lua_socket_tcp_receiveuntil(lua_State *L)
ngx_str_t pat;
ngx_int_t rc;
size_t size;
+ unsigned inclusive;
ngx_http_lua_socket_compiled_pattern_t *cp;
n = lua_gettop(L);
- if (n != 2) {
+ if (n != 2 && n != 3) {
return luaL_error(L, "expecting 2 arguments "
"(including the object), but got %d", n);
}
+#if 1
+ if (n == 3) {
+ /* check out the options table */
+
+ if (lua_type(L, 3) != LUA_TTABLE) {
+ return luaL_error(L, "expecting table as the 3rd argument, "
+ "but got %s",
+ luaL_typename(L, 3));
+ }
+
+ lua_getfield(L, 3, "inclusive");
+ if (!lua_isnil(L, -1)) {
+ inclusive = 1;
+ }
+
+ lua_pop(L, 2);
+ }
+#endif
+
lua_getglobal(L, GLOBALS_SYMBOL_REQUEST);
r = lua_touserdata(L, -1);
lua_pop(L, 1);
@@ -2196,6 +2216,8 @@ ngx_http_lua_socket_tcp_receiveuntil(lua_State *L)
ngx_memzero(cp, size);
+ cp->inclusive = inclusive;
+
rc = ngx_http_lua_socket_compile_pattern(pat.data, pat.len, cp,
r->connection->log);
diff --git a/src/ngx_http_lua_socket.h b/src/ngx_http_lua_socket.h
index 127ca50..42b52bb 100644
--- a/src/ngx_http_lua_socket.h
+++ b/src/ngx_http_lua_socket.h
@@ -93,6 +93,7 @@ typedef struct {
ngx_str_t pattern;
int state;
ngx_http_lua_dfa_edge_t **recovering;
+ unsigned inclusive;
} ngx_http_lua_socket_compiled_pattern_t;
> I took inspiration of what you do to parse a subrequests options table in:
> ngx_http_lua_ngx_location_capture_multi()
>
> One of the key difference is this line that I don't understand :
> lua_rawgeti(L, 2, 2); /* queries query uri opts */
>
The capture_multi method accepts arguments like {uri, opts}, and this
line means extracting the opts part from the {uri, opts} table.
Regards,
-agentzh