From cb9feb34bd263d3c0390c2ca2c55c887026ba945 Mon Sep 17 00:00:00 2001 From: zhengfangxin Date: Sat, 26 Sep 2015 21:03:38 +0800 Subject: [PATCH 01/18] delete two no need call clear_closed_event --- skynet-src/socket_server.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/skynet-src/socket_server.c b/skynet-src/socket_server.c index 7724a3c5..4963dd37 100644 --- a/skynet-src/socket_server.c +++ b/skynet-src/socket_server.c @@ -1176,6 +1176,7 @@ clear_closed_event(struct socket_server *ss, struct socket_message * result, int if (s) { if (s->type == SOCKET_TYPE_INVALID && s->id == id) { e->s = NULL; + break; } } } @@ -1245,21 +1246,19 @@ socket_server_poll(struct socket_server *ss, struct socket_message * result, int return SOCKET_UDP; } } - if (e->write) { + if (e->write && type != SOCKET_CLOSE && type != SOCKET_ERROR) { // Try to dispatch write message next step if write flag set. e->read = false; --ss->event_index; } if (type == -1) - break; - clear_closed_event(ss, result, type); + break; return type; } if (e->write) { int type = send_buffer(ss, s, result); if (type == -1) break; - clear_closed_event(ss, result, type); return type; } break; From 97ff6afc8438a22a630bd0acb102555b21760c1d Mon Sep 17 00:00:00 2001 From: xjdrew Date: Tue, 29 Sep 2015 17:29:33 +0800 Subject: [PATCH 02/18] removte unused code --- service-src/service_gate.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/service-src/service_gate.c b/service-src/service_gate.c index d59b4050..29eab2ea 100644 --- a/service-src/service_gate.c +++ b/service-src/service_gate.c @@ -335,13 +335,12 @@ gate_init(struct gate *g , struct skynet_context * ctx, char * parm) { if (parm == NULL) return 1; int max = 0; - int buffer = 0; int sz = strlen(parm)+1; char watchdog[sz]; char binding[sz]; int client_tag = 0; char header; - int n = sscanf(parm, "%c %s %s %d %d %d",&header,watchdog, binding,&client_tag , &max,&buffer); + int n = sscanf(parm, "%c %s %s %d %d %d", &header, watchdog, binding, &client_tag, &max); if (n<4) { skynet_error(ctx, "Invalid gate parm %s",parm); return 1; From 97fd5053c9c46fbca4990b353e412d49129f68ae Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Mon, 5 Oct 2015 09:56:12 +0800 Subject: [PATCH 03/18] update lpeg to 1.0.0 --- 3rd/lpeg/HISTORY | 8 +- 3rd/lpeg/lpcap.c | 4 +- 3rd/lpeg/lpcap.h | 4 +- 3rd/lpeg/lpcode.c | 22 +-- 3rd/lpeg/lpcode.h | 10 +- 3rd/lpeg/lpeg.html | 27 +-- 3rd/lpeg/lpprint.c | 8 +- 3rd/lpeg/lpprint.h | 3 +- 3rd/lpeg/lptree.c | 446 +++++++++++++++++++++++++-------------------- 3rd/lpeg/lptypes.h | 34 ++-- 3rd/lpeg/lpvm.c | 6 +- 3rd/lpeg/re.html | 8 +- 3rd/lpeg/test.lua | 55 +++++- 13 files changed, 376 insertions(+), 259 deletions(-) diff --git a/3rd/lpeg/HISTORY b/3rd/lpeg/HISTORY index 8ada7743..0c10edd0 100644 --- a/3rd/lpeg/HISTORY +++ b/3rd/lpeg/HISTORY @@ -1,4 +1,10 @@ -HISTORY for LPeg 0.12 +HISTORY for LPeg 1.0 + +* Changes from version 0.12 to 1.0 + --------------------------------- + + group "names" can be any Lua value + + some bugs fixed + + other small improvements * Changes from version 0.11 to 0.12 --------------------------------- diff --git a/3rd/lpeg/lpcap.c b/3rd/lpeg/lpcap.c index b6911cb1..c9085de0 100644 --- a/3rd/lpeg/lpcap.c +++ b/3rd/lpeg/lpcap.c @@ -1,5 +1,5 @@ /* -** $Id: lpcap.c,v 1.5 2014/12/12 16:58:47 roberto Exp $ +** $Id: lpcap.c,v 1.6 2015/06/15 16:09:57 roberto Exp $ ** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license) */ @@ -126,7 +126,7 @@ static Capture *findback (CapState *cs, Capture *cap) { continue; /* opening an enclosing capture: skip and get previous */ if (captype(cap) == Cgroup) { getfromktable(cs, cap->idx); /* get group name */ - if (lua_equal(L, -2, -1)) { /* right group? */ + if (lp_equal(L, -2, -1)) { /* right group? */ lua_pop(L, 2); /* remove reference name and group name */ return cap; } diff --git a/3rd/lpeg/lpcap.h b/3rd/lpeg/lpcap.h index c0a0e382..d762fdcf 100644 --- a/3rd/lpeg/lpcap.h +++ b/3rd/lpeg/lpcap.h @@ -1,5 +1,5 @@ /* -** $Id: lpcap.h,v 1.1 2013/03/21 20:25:12 roberto Exp $ +** $Id: lpcap.h,v 1.2 2015/02/27 17:13:17 roberto Exp $ */ #if !defined(lpcap_h) @@ -18,7 +18,7 @@ typedef enum CapKind { typedef struct Capture { const char *s; /* subject position */ - short idx; /* extra info about capture (group name, arg index, etc.) */ + unsigned short idx; /* extra info (group name, arg index, etc.) */ byte kind; /* kind of capture */ byte siz; /* size of full capture + 1 (0 = not a full capture) */ } Capture; diff --git a/3rd/lpeg/lpcode.c b/3rd/lpeg/lpcode.c index 93c0d2aa..fbf44feb 100644 --- a/3rd/lpeg/lpcode.c +++ b/3rd/lpeg/lpcode.c @@ -1,5 +1,5 @@ /* -** $Id: lpcode.c,v 1.21 2014/12/12 17:01:29 roberto Exp $ +** $Id: lpcode.c,v 1.23 2015/06/12 18:36:47 roberto Exp $ ** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license) */ @@ -431,11 +431,11 @@ typedef struct CompileState { /* -** code generation is recursive; 'opt' indicates that the code is -** being generated under a 'IChoice' operator jumping to its end -** (that is, the match is "optional"). -** 'tt' points to a previous test protecting this code. 'fl' is -** the follow set of the pattern. +** code generation is recursive; 'opt' indicates that the code is being +** generated as the last thing inside an optional pattern (so, if that +** code is optional too, it can reuse the 'IChoice' already in place for +** the outer pattern). 'tt' points to a previous test protecting this +** code (or NOINST). 'fl' is the follow set of the pattern. */ static void codegen (CompileState *compst, TTree *tree, int opt, int tt, const Charset *fl); @@ -638,13 +638,13 @@ static void codebehind (CompileState *compst, TTree *tree) { /* ** Choice; optimizations: -** - when p1 is headfail -** - when first(p1) and first(p2) are disjoint; than +** - when p1 is headfail or +** when first(p1) and first(p2) are disjoint, than ** a character not in first(p1) cannot go to p1, and a character ** in first(p1) cannot go to p2 (at it is not in first(p2)). ** (The optimization is not valid if p1 accepts the empty string, ** as then there is no character at all...) -** - when p2 is empty and opt is true; a IPartialCommit can resuse +** - when p2 is empty and opt is true; a IPartialCommit can reuse ** the Choice already active in the stack. */ static void codechoice (CompileState *compst, TTree *p1, TTree *p2, int opt, @@ -671,7 +671,7 @@ static void codechoice (CompileState *compst, TTree *p1, TTree *p2, int opt, } else { /* == - test(fail(p1)) -> L1; choice L1; ; commit L2; L1: ; L2: */ + test(first(p1)) -> L1; choice L1; ; commit L2; L1: ; L2: */ int pcommit; int test = codetestset(compst, &cs1, e1); int pchoice = addoffsetinst(compst, IChoice); @@ -759,7 +759,7 @@ static void coderep (CompileState *compst, TTree *tree, int opt, /* L1: test (fail(p1)) -> L2;

; jmp L1; L2: */ int jmp; int test = codetestset(compst, &st, 0); - codegen(compst, tree, opt, test, fullset); + codegen(compst, tree, 0, test, fullset); jmp = addoffsetinst(compst, IJmp); jumptohere(compst, test); jumptothere(compst, jmp, test); diff --git a/3rd/lpeg/lpcode.h b/3rd/lpeg/lpcode.h index 72d2bb94..896d3c79 100644 --- a/3rd/lpeg/lpcode.h +++ b/3rd/lpeg/lpcode.h @@ -1,5 +1,5 @@ /* -** $Id: lpcode.h,v 1.6 2013/11/28 14:56:02 roberto Exp $ +** $Id: lpcode.h,v 1.7 2015/06/12 18:24:45 roberto Exp $ */ #if !defined(lpcode_h) @@ -24,7 +24,15 @@ int sizei (const Instruction *i); #define PEnullable 0 #define PEnofail 1 +/* +** nofail(t) implies that 't' cannot fail with any input +*/ #define nofail(t) checkaux(t, PEnofail) + +/* +** (not nullable(t)) implies 't' cannot match without consuming +** something +*/ #define nullable(t) checkaux(t, PEnullable) #define fixedlen(t) fixedlenx(t, 0, 0) diff --git a/3rd/lpeg/lpeg.html b/3rd/lpeg/lpeg.html index 0eb1747f..c0a7f090 100644 --- a/3rd/lpeg/lpeg.html +++ b/3rd/lpeg/lpeg.html @@ -10,7 +10,7 @@ - +

@@ -22,7 +22,7 @@
LPeg
- Parsing Expression Grammars For Lua, version 0.12 + Parsing Expression Grammars For Lua, version 1.0
@@ -195,13 +195,16 @@ Returns a string with the running version of LPeg.

lpeg.setmaxstack (max)

-Sets the maximum size for the backtrack stack used by LPeg to +Sets a limit for the size of the backtrack stack used by LPeg to track calls and choices. +(The default limit is 400.) Most well-written patterns need little backtrack levels and -therefore you seldom need to change this maximum; -but a few useful patterns may need more space. -Before changing this maximum you should try to rewrite your +therefore you seldom need to change this limit; +before changing it you should try to rewrite your pattern to avoid the need for extra space. +Nevertheless, a few useful patterns may overflow. +Also, with recursive grammars, +subjects with deep recursion may also need larger limits.

@@ -682,7 +685,8 @@ argument given in the call to lpeg.match. Creates a back capture. This pattern matches the empty string and produces the values produced by the most recent -group capture named name. +group capture named name +(where name can be any Lua value).

@@ -762,7 +766,8 @@ Creates a group capture. It groups all values returned by patt into a single capture. The group may be anonymous (if no name is given) -or named with the given name. +or named with the given name +(which can be any non-nil Lua value).

@@ -1375,13 +1380,13 @@ and the new term for each repetition.

Download

LPeg -source code.

+source code.

License

-Copyright © 2014 Lua.org, PUC-Rio. +Copyright © 2007-2015 Lua.org, PUC-Rio.

Permission is hereby granted, free of charge, @@ -1419,7 +1424,7 @@ THE SOFTWARE.

-$Id: lpeg.html,v 1.72 2014/12/12 17:11:35 roberto Exp $ +$Id: lpeg.html,v 1.75 2015/09/28 17:17:41 roberto Exp $

diff --git a/3rd/lpeg/lpprint.c b/3rd/lpeg/lpprint.c index 05fa6488..174d1687 100644 --- a/3rd/lpeg/lpprint.c +++ b/3rd/lpeg/lpprint.c @@ -1,5 +1,5 @@ /* -** $Id: lpprint.c,v 1.7 2013/04/12 16:29:49 roberto Exp $ +** $Id: lpprint.c,v 1.9 2015/06/15 16:09:57 roberto Exp $ ** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license) */ @@ -52,7 +52,7 @@ static void printjmp (const Instruction *op, const Instruction *p) { } -static void printinst (const Instruction *op, const Instruction *p) { +void printinst (const Instruction *op, const Instruction *p) { const char *const names[] = { "any", "char", "set", "testany", "testchar", "testset", @@ -221,10 +221,10 @@ void printtree (TTree *tree, int ident) { void printktable (lua_State *L, int idx) { int n, i; - lua_getfenv(L, idx); + lua_getuservalue(L, idx); if (lua_isnil(L, -1)) /* no ktable? */ return; - n = lua_objlen(L, -1); + n = lua_rawlen(L, -1); printf("["); for (i = 1; i <= n; i++) { printf("%d = ", i); diff --git a/3rd/lpeg/lpprint.h b/3rd/lpeg/lpprint.h index e640f744..63297607 100644 --- a/3rd/lpeg/lpprint.h +++ b/3rd/lpeg/lpprint.h @@ -1,5 +1,5 @@ /* -** $Id: lpprint.h,v 1.1 2013/03/21 20:25:12 roberto Exp $ +** $Id: lpprint.h,v 1.2 2015/06/12 18:18:08 roberto Exp $ */ @@ -18,6 +18,7 @@ void printtree (TTree *tree, int ident); void printktable (lua_State *L, int idx); void printcharset (const byte *st); void printcaplist (Capture *cap, Capture *limit); +void printinst (const Instruction *op, const Instruction *p); #else diff --git a/3rd/lpeg/lptree.c b/3rd/lpeg/lptree.c index 7c5b8200..ac5f5150 100644 --- a/3rd/lpeg/lptree.c +++ b/3rd/lpeg/lptree.c @@ -1,5 +1,5 @@ /* -** $Id: lptree.c,v 1.13 2014/12/12 16:59:10 roberto Exp $ +** $Id: lptree.c,v 1.21 2015/09/28 17:01:25 roberto Exp $ ** Copyright 2013, Lua.org & PUC-Rio (see 'lpeg.html' for license) */ @@ -126,6 +126,189 @@ static void finalfix (lua_State *L, int postable, TTree *g, TTree *t) { } + +/* +** {=================================================================== +** KTable manipulation +** +** - The ktable of a pattern 'p' can be shared by other patterns that +** contain 'p' and no other constants. Because of this sharing, we +** should not add elements to a 'ktable' unless it was freshly created +** for the new pattern. +** +** - The maximum index in a ktable is USHRT_MAX, because trees and +** patterns use unsigned shorts to store those indices. +** ==================================================================== +*/ + +/* +** Create a new 'ktable' to the pattern at the top of the stack. +*/ +static void newktable (lua_State *L, int n) { + lua_createtable(L, n, 0); /* create a fresh table */ + lua_setuservalue(L, -2); /* set it as 'ktable' for pattern */ +} + + +/* +** Add element 'idx' to 'ktable' of pattern at the top of the stack; +** Return index of new element. +** If new element is nil, does not add it to table (as it would be +** useless) and returns 0, as ktable[0] is always nil. +*/ +static int addtoktable (lua_State *L, int idx) { + if (lua_isnil(L, idx)) /* nil value? */ + return 0; + else { + int n; + lua_getuservalue(L, -1); /* get ktable from pattern */ + n = lua_rawlen(L, -1); + if (n >= USHRT_MAX) + luaL_error(L, "too many Lua values in pattern"); + lua_pushvalue(L, idx); /* element to be added */ + lua_rawseti(L, -2, ++n); + lua_pop(L, 1); /* remove 'ktable' */ + return n; + } +} + + +/* +** Return the number of elements in the ktable at 'idx'. +** In Lua 5.2/5.3, default "environment" for patterns is nil, not +** a table. Treat it as an empty table. In Lua 5.1, assumes that +** the environment has no numeric indices (len == 0) +*/ +static int ktablelen (lua_State *L, int idx) { + if (!lua_istable(L, idx)) return 0; + else return lua_rawlen(L, idx); +} + + +/* +** Concatentate the contents of table 'idx1' into table 'idx2'. +** (Assume that both indices are negative.) +** Return the original length of table 'idx2' (or 0, if no +** element was added, as there is no need to correct any index). +*/ +static int concattable (lua_State *L, int idx1, int idx2) { + int i; + int n1 = ktablelen(L, idx1); + int n2 = ktablelen(L, idx2); + if (n1 + n2 > USHRT_MAX) + luaL_error(L, "too many Lua values in pattern"); + if (n1 == 0) return 0; /* nothing to correct */ + for (i = 1; i <= n1; i++) { + lua_rawgeti(L, idx1, i); + lua_rawseti(L, idx2 - 1, n2 + i); /* correct 'idx2' */ + } + return n2; +} + + +/* +** When joining 'ktables', constants from one of the subpatterns must +** be renumbered; 'correctkeys' corrects their indices (adding 'n' +** to each of them) +*/ +static void correctkeys (TTree *tree, int n) { + if (n == 0) return; /* no correction? */ + tailcall: + switch (tree->tag) { + case TOpenCall: case TCall: case TRunTime: case TRule: { + if (tree->key > 0) + tree->key += n; + break; + } + case TCapture: { + if (tree->key > 0 && tree->cap != Carg && tree->cap != Cnum) + tree->key += n; + break; + } + default: break; + } + switch (numsiblings[tree->tag]) { + case 1: /* correctkeys(sib1(tree), n); */ + tree = sib1(tree); goto tailcall; + case 2: + correctkeys(sib1(tree), n); + tree = sib2(tree); goto tailcall; /* correctkeys(sib2(tree), n); */ + default: assert(numsiblings[tree->tag] == 0); break; + } +} + + +/* +** Join the ktables from p1 and p2 the ktable for the new pattern at the +** top of the stack, reusing them when possible. +*/ +static void joinktables (lua_State *L, int p1, TTree *t2, int p2) { + int n1, n2; + lua_getuservalue(L, p1); /* get ktables */ + lua_getuservalue(L, p2); + n1 = ktablelen(L, -2); + n2 = ktablelen(L, -1); + if (n1 == 0 && n2 == 0) /* are both tables empty? */ + lua_pop(L, 2); /* nothing to be done; pop tables */ + else if (n2 == 0 || lp_equal(L, -2, -1)) { /* 2nd table empty or equal? */ + lua_pop(L, 1); /* pop 2nd table */ + lua_setuservalue(L, -2); /* set 1st ktable into new pattern */ + } + else if (n1 == 0) { /* first table is empty? */ + lua_setuservalue(L, -3); /* set 2nd table into new pattern */ + lua_pop(L, 1); /* pop 1st table */ + } + else { + lua_createtable(L, n1 + n2, 0); /* create ktable for new pattern */ + /* stack: new p; ktable p1; ktable p2; new ktable */ + concattable(L, -3, -1); /* from p1 into new ktable */ + concattable(L, -2, -1); /* from p2 into new ktable */ + lua_setuservalue(L, -4); /* new ktable becomes 'p' environment */ + lua_pop(L, 2); /* pop other ktables */ + correctkeys(t2, n1); /* correction for indices from p2 */ + } +} + + +/* +** copy 'ktable' of element 'idx' to new tree (on top of stack) +*/ +static void copyktable (lua_State *L, int idx) { + lua_getuservalue(L, idx); + lua_setuservalue(L, -2); +} + + +/* +** merge 'ktable' from 'stree' at stack index 'idx' into 'ktable' +** from tree at the top of the stack, and correct corresponding +** tree. +*/ +static void mergektable (lua_State *L, int idx, TTree *stree) { + int n; + lua_getuservalue(L, -1); /* get ktables */ + lua_getuservalue(L, idx); + n = concattable(L, -1, -2); + lua_pop(L, 2); /* remove both ktables */ + correctkeys(stree, n); +} + + +/* +** Create a new 'ktable' to the pattern at the top of the stack, adding +** all elements from pattern 'p' (if not 0) plus element 'idx' to it. +** Return index of new element. +*/ +static int addtonewktable (lua_State *L, int p, int idx) { + newktable(L, 1); + if (p) + mergektable(L, p, NULL); + return addtoktable(L, idx); +} + +/* }====================================================== */ + + /* ** {====================================================== ** Tree generation @@ -155,7 +338,7 @@ static Pattern *getpattern (lua_State *L, int idx) { static int getsize (lua_State *L, int idx) { - return (lua_objlen(L, idx) - sizeof(Pattern)) / sizeof(TTree) + 1; + return (lua_rawlen(L, idx) - sizeof(Pattern)) / sizeof(TTree) + 1; } @@ -168,12 +351,16 @@ static TTree *gettree (lua_State *L, int idx, int *len) { /* -** create a pattern +** create a pattern. Set its uservalue (the 'ktable') equal to its +** metatable. (It could be any empty sequence; the metatable is at +** hand here, so we use it.) */ static TTree *newtree (lua_State *L, int len) { size_t size = (len - 1) * sizeof(TTree) + sizeof(Pattern); Pattern *p = (Pattern *)lua_newuserdata(L, size); luaL_getmetatable(L, PATTERN_T); + lua_pushvalue(L, -1); + lua_setuservalue(L, -3); lua_setmetatable(L, -2); p->code = NULL; p->codesize = 0; return p->tree; @@ -206,35 +393,6 @@ static TTree *seqaux (TTree *tree, TTree *sib, int sibsize) { } -/* -** Add element 'idx' to 'ktable' of pattern at the top of the stack; -** create new 'ktable' if necessary. Return index of new element. -** If new element is nil, does not add it to table (as it would be -** useless) and returns 0, as ktable[0] is always nil. -*/ -static int addtoktable (lua_State *L, int idx) { - if (idx == 0) /* no actual value to insert? */ - return 0; - else { - int n; - lua_getfenv(L, -1); /* get ktable from pattern */ - n = lua_objlen(L, -1); - if (n == 0) { /* is it empty/non-existent? */ - lua_pop(L, 1); /* remove it */ - lua_createtable(L, 1, 0); /* create a fresh table */ - lua_pushvalue(L, -1); /* make a copy */ - lua_setfenv(L, -3); /* set it as 'ktable' for pattern */ - } - if (!lua_isnil(L, idx)) { /* non-nil value? */ - lua_pushvalue(L, idx); /* element to be added */ - lua_rawseti(L, -2, ++n); - } - lua_pop(L, 1); /* remove 'ktable' */ - return n; - } -} - - /* ** Build a sequence of 'n' nodes, each with tag 'tag' and 'u.n' got ** from the array 's' (or 0 if array is NULL). (TSeq is binary, so it @@ -310,7 +468,7 @@ static TTree *getpatt (lua_State *L, int idx, int *len) { case LUA_TFUNCTION: { tree = newtree(L, 2); tree->tag = TRunTime; - tree->key = addtoktable(L, idx); + tree->key = addtonewktable(L, 0, idx); sib1(tree)->tag = TTrue; break; } @@ -325,123 +483,6 @@ static TTree *getpatt (lua_State *L, int idx, int *len) { } -/* -** Return the number of elements in the ktable of pattern at 'idx'. -** In Lua 5.2, default "environment" for patterns is nil, not -** a table. Treat it as an empty table. In Lua 5.1, assumes that -** the environment has no numeric indices (len == 0) -*/ -static int ktablelen (lua_State *L, int idx) { - if (!lua_istable(L, idx)) return 0; - else return lua_objlen(L, idx); -} - - -/* -** Concatentate the contents of table 'idx1' into table 'idx2'. -** (Assume that both indices are negative.) -** Return the original length of table 'idx2' -*/ -static int concattable (lua_State *L, int idx1, int idx2) { - int i; - int n1 = ktablelen(L, idx1); - int n2 = ktablelen(L, idx2); - if (n1 == 0) return 0; /* nothing to correct */ - for (i = 1; i <= n1; i++) { - lua_rawgeti(L, idx1, i); - lua_rawseti(L, idx2 - 1, n2 + i); /* correct 'idx2' */ - } - return n2; -} - - -/* -** Make a merge of ktables from p1 and p2 the ktable for the new -** pattern at the top of the stack. -*/ -static int joinktables (lua_State *L, int p1, int p2) { - int n1, n2; - lua_getfenv(L, p1); /* get ktables */ - lua_getfenv(L, p2); - n1 = ktablelen(L, -2); - n2 = ktablelen(L, -1); - if (n1 == 0 && n2 == 0) { /* are both tables empty? */ - lua_pop(L, 2); /* nothing to be done; pop tables */ - return 0; /* nothing to correct */ - } - if (n2 == 0 || lua_equal(L, -2, -1)) { /* second table is empty or equal? */ - lua_pop(L, 1); /* pop 2nd table */ - lua_setfenv(L, -2); /* set 1st ktable into new pattern */ - return 0; /* nothing to correct */ - } - if (n1 == 0) { /* first table is empty? */ - lua_setfenv(L, -3); /* set 2nd table into new pattern */ - lua_pop(L, 1); /* pop 1st table */ - return 0; /* nothing to correct */ - } - else { - lua_createtable(L, n1 + n2, 0); /* create ktable for new pattern */ - /* stack: new p; ktable p1; ktable p2; new ktable */ - concattable(L, -3, -1); /* from p1 into new ktable */ - concattable(L, -2, -1); /* from p2 into new ktable */ - lua_setfenv(L, -4); /* new ktable becomes p env */ - lua_pop(L, 2); /* pop other ktables */ - return n1; /* correction for indices from p2 */ - } -} - - -static void correctkeys (TTree *tree, int n) { - if (n == 0) return; /* no correction? */ - tailcall: - switch (tree->tag) { - case TOpenCall: case TCall: case TRunTime: case TRule: { - if (tree->key > 0) - tree->key += n; - break; - } - case TCapture: { - if (tree->key > 0 && tree->cap != Carg && tree->cap != Cnum) - tree->key += n; - break; - } - default: break; - } - switch (numsiblings[tree->tag]) { - case 1: /* correctkeys(sib1(tree), n); */ - tree = sib1(tree); goto tailcall; - case 2: - correctkeys(sib1(tree), n); - tree = sib2(tree); goto tailcall; /* correctkeys(sib2(tree), n); */ - default: assert(numsiblings[tree->tag] == 0); break; - } -} - - -/* -** copy 'ktable' of element 'idx' to new tree (on top of stack) -*/ -static void copyktable (lua_State *L, int idx) { - lua_getfenv(L, idx); - lua_setfenv(L, -2); -} - - -/* -** merge 'ktable' from rule at stack index 'idx' into 'ktable' -** from tree at the top of the stack, and correct corresponding -** tree. -*/ -static void mergektable (lua_State *L, int idx, TTree *rule) { - int n; - lua_getfenv(L, -1); /* get ktables */ - lua_getfenv(L, idx); - n = concattable(L, -1, -2); - lua_pop(L, 2); /* remove both ktables */ - correctkeys(rule, n); -} - - /* ** create a new tree, whith a new root and one sibling. ** Sibling must be on the Lua stack, at index 1. @@ -470,7 +511,7 @@ static TTree *newroot2sib (lua_State *L, int tag) { tree->u.ps = 1 + s1; memcpy(sib1(tree), tree1, s1 * sizeof(TTree)); memcpy(sib2(tree), tree2, s2 * sizeof(TTree)); - correctkeys(sib2(tree), joinktables(L, 1, 2)); + joinktables(L, 1, sib2(tree), 2); return tree; } @@ -599,7 +640,7 @@ static int lp_sub (lua_State *L) { sib1(tree)->tag = TNot; /* ...not... */ memcpy(sib1(sib1(tree)), t2, s2 * sizeof(TTree)); /* ...t2 */ memcpy(sib2(tree), t1, s1 * sizeof(TTree)); /* ... and t1 */ - correctkeys(sib1(tree), joinktables(L, 1, 2)); + joinktables(L, 1, sib1(tree), 2); } return 1; } @@ -640,7 +681,7 @@ static int lp_behind (lua_State *L) { TTree *tree; TTree *tree1 = getpatt(L, 1, NULL); int n = fixedlen(tree1); - luaL_argcheck(L, n > 0, 1, "pattern may not have fixed length"); + luaL_argcheck(L, n >= 0, 1, "pattern may not have fixed length"); luaL_argcheck(L, !hascaptures(tree1), 1, "pattern have captures"); luaL_argcheck(L, n <= MAXBEHIND, 1, "pattern too long to look behind"); tree = newroot1sib(L, TBehind); @@ -655,7 +696,7 @@ static int lp_behind (lua_State *L) { static int lp_V (lua_State *L) { TTree *tree = newleaf(L, TOpenCall); luaL_argcheck(L, !lua_isnoneornil(L, 1), 1, "non-nil value expected"); - tree->key = addtoktable(L, 1); + tree->key = addtonewktable(L, 0, 1); return 1; } @@ -668,7 +709,7 @@ static int lp_V (lua_State *L) { static int capture_aux (lua_State *L, int cap, int labelidx) { TTree *tree = newroot1sib(L, TCapture); tree->cap = cap; - tree->key = addtoktable(L, labelidx); + tree->key = (labelidx == 0) ? 0 : addtonewktable(L, 1, labelidx); return 1; } @@ -676,10 +717,9 @@ static int capture_aux (lua_State *L, int cap, int labelidx) { /* ** Fill a tree with an empty capture, using an empty (TTrue) sibling. */ -static TTree *auxemptycap (lua_State *L, TTree *tree, int cap, int idx) { +static TTree *auxemptycap (TTree *tree, int cap) { tree->tag = TCapture; tree->cap = cap; - tree->key = addtoktable(L, idx); sib1(tree)->tag = TTrue; return tree; } @@ -688,8 +728,18 @@ static TTree *auxemptycap (lua_State *L, TTree *tree, int cap, int idx) { /* ** Create a tree for an empty capture */ -static TTree *newemptycap (lua_State *L, int cap, int idx) { - return auxemptycap(L, newtree(L, 2), cap, idx); +static TTree *newemptycap (lua_State *L, int cap) { + return auxemptycap(newtree(L, 2), cap); +} + + +/* +** Create a tree for an empty capture with an associated Lua value +*/ +static TTree *newemptycapkey (lua_State *L, int cap, int idx) { + TTree *tree = auxemptycap(newtree(L, 2), cap); + tree->key = addtonewktable(L, 0, idx); + return tree; } @@ -728,10 +778,8 @@ static int lp_tablecapture (lua_State *L) { static int lp_groupcapture (lua_State *L) { if (lua_isnoneornil(L, 2)) return capture_aux(L, Cgroup, 0); - else { - luaL_checkstring(L, 2); + else return capture_aux(L, Cgroup, 2); - } } @@ -747,14 +795,14 @@ static int lp_simplecapture (lua_State *L) { static int lp_poscapture (lua_State *L) { - newemptycap(L, Cposition, 0); + newemptycap(L, Cposition); return 1; } static int lp_argcapture (lua_State *L) { int n = (int)luaL_checkinteger(L, 1); - TTree *tree = newemptycap(L, Carg, 0); + TTree *tree = newemptycap(L, Carg); tree->key = n; luaL_argcheck(L, 0 < n && n <= SHRT_MAX, 1, "invalid argument index"); return 1; @@ -762,8 +810,8 @@ static int lp_argcapture (lua_State *L) { static int lp_backref (lua_State *L) { - luaL_checkstring(L, 1); - newemptycap(L, Cbackref, 1); + luaL_checkany(L, 1); + newemptycapkey(L, Cbackref, 1); return 1; } @@ -777,9 +825,10 @@ static int lp_constcapture (lua_State *L) { if (n == 0) /* no values? */ newleaf(L, TTrue); /* no capture */ else if (n == 1) - newemptycap(L, Cconst, 1); /* single constant capture */ + newemptycapkey(L, Cconst, 1); /* single constant capture */ else { /* create a group capture with all values */ TTree *tree = newtree(L, 1 + 3 * (n - 1) + 2); + newktable(L, n); /* create a 'ktable' for new tree */ tree->tag = TCapture; tree->cap = Cgroup; tree->key = 0; @@ -787,10 +836,12 @@ static int lp_constcapture (lua_State *L) { for (i = 1; i <= n - 1; i++) { tree->tag = TSeq; tree->u.ps = 3; /* skip TCapture and its sibling */ - auxemptycap(L, sib1(tree), Cconst, i); + auxemptycap(sib1(tree), Cconst); + sib1(tree)->key = addtoktable(L, i); tree = sib2(tree); } - auxemptycap(L, tree, Cconst, i); + auxemptycap(tree, Cconst); + tree->key = addtoktable(L, i); } return 1; } @@ -800,7 +851,7 @@ static int lp_matchtime (lua_State *L) { TTree *tree; luaL_checktype(L, 2, LUA_TFUNCTION); tree = newroot1sib(L, TRunTime); - tree->key = addtoktable(L, 2); + tree->key = addtonewktable(L, 1, 2); return 1; } @@ -857,7 +908,7 @@ static int collectrules (lua_State *L, int arg, int *totalsize) { lua_pushnil(L); /* prepare to traverse grammar table */ while (lua_next(L, arg) != 0) { if (lua_tonumber(L, -2) == 1 || - lua_equal(L, -2, postab + 1)) { /* initial rule? */ + lp_equal(L, -2, postab + 1)) { /* initial rule? */ lua_pop(L, 1); /* remove value (keep key for lua_next) */ continue; } @@ -934,36 +985,40 @@ static int verifyerror (lua_State *L, int *passed, int npassed) { /* ** Check whether a rule can be left recursive; raise an error in that -** case; otherwise return 1 iff pattern is nullable. Assume ktable at -** the top of the stack. +** case; otherwise return 1 iff pattern is nullable. +** The return value is used to check sequences, where the second pattern +** is only relevant if the first is nullable. +** Parameter 'nb' works as an accumulator, to allow tail calls in +** choices. ('nb' true makes function returns true.) +** Assume ktable at the top of the stack. */ static int verifyrule (lua_State *L, TTree *tree, int *passed, int npassed, - int nullable) { + int nb) { tailcall: switch (tree->tag) { case TChar: case TSet: case TAny: case TFalse: - return nullable; /* cannot pass from here */ + return nb; /* cannot pass from here */ case TTrue: case TBehind: /* look-behind cannot have calls */ return 1; case TNot: case TAnd: case TRep: /* return verifyrule(L, sib1(tree), passed, npassed, 1); */ - tree = sib1(tree); nullable = 1; goto tailcall; + tree = sib1(tree); nb = 1; goto tailcall; case TCapture: case TRunTime: - /* return verifyrule(L, sib1(tree), passed, npassed); */ + /* return verifyrule(L, sib1(tree), passed, npassed, nb); */ tree = sib1(tree); goto tailcall; case TCall: - /* return verifyrule(L, sib2(tree), passed, npassed); */ + /* return verifyrule(L, sib2(tree), passed, npassed, nb); */ tree = sib2(tree); goto tailcall; - case TSeq: /* only check 2nd child if first is nullable */ + case TSeq: /* only check 2nd child if first is nb */ if (!verifyrule(L, sib1(tree), passed, npassed, 0)) - return nullable; - /* else return verifyrule(L, sib2(tree), passed, npassed); */ + return nb; + /* else return verifyrule(L, sib2(tree), passed, npassed, nb); */ tree = sib2(tree); goto tailcall; case TChoice: /* must check both children */ - nullable = verifyrule(L, sib1(tree), passed, npassed, nullable); - /* return verifyrule(L, sib2(tree), passed, npassed, nullable); */ + nb = verifyrule(L, sib1(tree), passed, npassed, nb); + /* return verifyrule(L, sib2(tree), passed, npassed, nb); */ tree = sib2(tree); goto tailcall; case TRule: if (npassed >= MAXRULES) @@ -1006,7 +1061,7 @@ static void verifygrammar (lua_State *L, TTree *grammar) { */ static void initialrulename (lua_State *L, TTree *grammar, int frule) { if (sib1(grammar)->key == 0) { /* initial rule is not referenced? */ - int n = lua_objlen(L, -1) + 1; /* index for name */ + int n = lua_rawlen(L, -1) + 1; /* index for name */ lua_pushvalue(L, frule); /* rule's name */ lua_rawseti(L, -2, n); /* ktable was on the top of the stack */ sib1(grammar)->key = n; @@ -1022,9 +1077,9 @@ static TTree *newgrammar (lua_State *L, int arg) { luaL_argcheck(L, n <= MAXRULES, arg, "grammar has too many rules"); g->tag = TGrammar; g->u.n = n; lua_newtable(L); /* create 'ktable' */ - lua_setfenv(L, -2); + lua_setuservalue(L, -2); buildgrammar(L, g, frule, n); - lua_getfenv(L, -1); /* get 'ktable' for new tree */ + lua_getuservalue(L, -1); /* get 'ktable' for new tree */ finalfix(L, frule - 1, g, sib1(g)); initialrulename(L, g, frule); verifygrammar(L, g); @@ -1038,7 +1093,7 @@ static TTree *newgrammar (lua_State *L, int arg) { static Instruction *prepcompile (lua_State *L, Pattern *p, int idx) { - lua_getfenv(L, idx); /* push 'ktable' (may be used by 'finalfix') */ + lua_getuservalue(L, idx); /* push 'ktable' (may be used by 'finalfix') */ finalfix(L, 0, NULL, p->tree); lua_pop(L, 1); /* remove 'ktable' */ return compile(L, p); @@ -1049,7 +1104,7 @@ static int lp_printtree (lua_State *L) { TTree *tree = getpatt(L, 1, NULL); int c = lua_toboolean(L, 2); if (c) { - lua_getfenv(L, 1); /* push 'ktable' (may be used by 'finalfix') */ + lua_getuservalue(L, 1); /* push 'ktable' (may be used by 'finalfix') */ finalfix(L, 0, NULL, tree); lua_pop(L, 1); /* remove 'ktable' */ } @@ -1102,7 +1157,7 @@ static int lp_match (lua_State *L) { int ptop = lua_gettop(L); lua_pushnil(L); /* initialize subscache */ lua_pushlightuserdata(L, capture); /* initialize caplistidx */ - lua_getfenv(L, 1); /* initialize penvidx */ + lua_getuservalue(L, 1); /* initialize penvidx */ r = match(L, s, s + i, s + l, code, capture, ptop); if (r == NULL) { lua_pushnil(L); @@ -1119,8 +1174,12 @@ static int lp_match (lua_State *L) { ** ======================================================= */ +/* maximum limit for stack size */ +#define MAXLIM (INT_MAX / 100) + static int lp_setmax (lua_State *L) { - luaL_optinteger(L, 1, -1); + lua_Integer lim = luaL_checkinteger(L, 1); + luaL_argcheck(L, 0 < lim && lim <= MAXLIM, 1, "out of range"); lua_settop(L, 1); lua_setfield(L, LUA_REGISTRYINDEX, MAXSTACKIDX); return 0; @@ -1144,8 +1203,7 @@ static int lp_type (lua_State *L) { int lp_gc (lua_State *L) { Pattern *p = getpattern(L, 1); - if (p->codesize > 0) - realloccode(L, p, 0); + realloccode(L, p, 0); /* delete code block */ return 0; } @@ -1228,8 +1286,8 @@ int luaopen_lpeg (lua_State *L) { luaL_newmetatable(L, PATTERN_T); lua_pushnumber(L, MAXBACK); /* initialize maximum backtracking */ lua_setfield(L, LUA_REGISTRYINDEX, MAXSTACKIDX); - luaL_register(L, NULL, metareg); - luaL_register(L, "lpeg", pattreg); + luaL_setfuncs(L, metareg, 0); + luaL_newlib(L, pattreg); lua_pushvalue(L, -1); lua_setfield(L, -3, "__index"); return 1; diff --git a/3rd/lpeg/lptypes.h b/3rd/lpeg/lptypes.h index b85c0c97..5eb7987b 100644 --- a/3rd/lpeg/lptypes.h +++ b/3rd/lpeg/lptypes.h @@ -1,7 +1,7 @@ /* -** $Id: lptypes.h,v 1.10 2014/12/12 17:11:35 roberto Exp $ +** $Id: lptypes.h,v 1.14 2015/09/28 17:17:41 roberto Exp $ ** LPeg - PEG pattern matching for Lua -** Copyright 2007-2014, Lua.org & PUC-Rio (see 'lpeg.html' for license) +** Copyright 2007-2015, Lua.org & PUC-Rio (see 'lpeg.html' for license) ** written by Roberto Ierusalimschy */ @@ -19,7 +19,7 @@ #include "lua.h" -#define VERSION "0.12.1" +#define VERSION "1.0.0" #define PATTERN_T "lpeg-pattern" @@ -27,31 +27,31 @@ /* -** compatibility with Lua 5.2 +** compatibility with Lua 5.1 */ -#if (LUA_VERSION_NUM >= 502) +#if (LUA_VERSION_NUM == 501) -#undef lua_equal -#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ) +#define lp_equal lua_equal -#undef lua_getfenv -#define lua_getfenv lua_getuservalue -#undef lua_setfenv -#define lua_setfenv lua_setuservalue +#define lua_getuservalue lua_getfenv +#define lua_setuservalue lua_setfenv -#undef lua_objlen -#define lua_objlen lua_rawlen +#define lua_rawlen lua_objlen -#undef luaL_register -#define luaL_register(L,n,f) \ - { if ((n) == NULL) luaL_setfuncs(L,f,0); else luaL_newlib(L,f); } +#define luaL_setfuncs(L,f,n) luaL_register(L,NULL,f) +#define luaL_newlib(L,f) luaL_register(L,"lpeg",f) #endif +#if !defined(lp_equal) +#define lp_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ) +#endif + + /* default maximum size for call/backtrack stack */ #if !defined(MAXBACK) -#define MAXBACK 100 +#define MAXBACK 400 #endif diff --git a/3rd/lpeg/lpvm.c b/3rd/lpeg/lpvm.c index cd893ed8..eaf2ebfd 100644 --- a/3rd/lpeg/lpvm.c +++ b/3rd/lpeg/lpvm.c @@ -1,5 +1,5 @@ /* -** $Id: lpvm.c,v 1.5 2013/04/12 16:29:49 roberto Exp $ +** $Id: lpvm.c,v 1.6 2015/09/28 17:01:25 roberto Exp $ ** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license) */ @@ -18,7 +18,7 @@ /* initial size for call/backtrack stack */ #if !defined(INITBACK) -#define INITBACK 100 +#define INITBACK MAXBACK #endif @@ -70,7 +70,7 @@ static Stack *doublestack (lua_State *L, Stack **stacklimit, int ptop) { max = lua_tointeger(L, -1); /* maximum allowed size */ lua_pop(L, 1); if (n >= max) /* already at maximum size? */ - luaL_error(L, "too many pending calls/choices"); + luaL_error(L, "backtrack stack overflow (current limit is %d)", max); newn = 2 * n; /* new size */ if (newn > max) newn = max; newstack = (Stack *)lua_newuserdata(L, newn * sizeof(Stack)); diff --git a/3rd/lpeg/re.html b/3rd/lpeg/re.html index 4717ec2b..d0d9744f 100644 --- a/3rd/lpeg/re.html +++ b/3rd/lpeg/re.html @@ -10,7 +10,7 @@ - +
@@ -296,7 +296,7 @@ it would be useful if each table had a tag field telling what non terminal that table represents. We can add such a tag using -named group captures: +named group captures:

 x = re.compile[[
@@ -450,7 +450,7 @@ print(re.match(p, p))   -- a self description must match itself
 

License

-Copyright © 2008-2010 Lua.org, PUC-Rio. +Copyright © 2008-2015 Lua.org, PUC-Rio.

Permission is hereby granted, free of charge, @@ -488,7 +488,7 @@ THE SOFTWARE.

-$Id: re.html,v 1.21 2013/03/28 20:43:30 roberto Exp $ +$Id: re.html,v 1.23 2015/09/28 17:17:41 roberto Exp $

diff --git a/3rd/lpeg/test.lua b/3rd/lpeg/test.lua index fec5a85b..017a3abf 100755 --- a/3rd/lpeg/test.lua +++ b/3rd/lpeg/test.lua @@ -1,6 +1,6 @@ -#!/usr/bin/env lua5.1 +#!/usr/bin/env lua --- $Id: test.lua,v 1.105 2014/12/12 17:00:39 roberto Exp $ +-- $Id: test.lua,v 1.109 2015/09/28 17:01:25 roberto Exp $ -- require"strict" -- just to be pedantic @@ -16,9 +16,6 @@ local unpack = rawget(table, "unpack") or unpack local loadstring = rawget(_G, "loadstring") or load --- most tests here do not need much stack space -m.setmaxstack(5) - local any = m.P(1) local space = m.S" \t\n"^0 @@ -291,6 +288,13 @@ assert(m.match(m.P"ab"^-1 - "c", "abcd") == 3) p = ('Aa' * ('Bb' * ('Cc' * m.P'Dd'^0)^0)^0)^-1 assert(p:match("AaBbCcDdBbCcDdDdDdBb") == 21) + + +-- bug in 0.12.2 +-- p = { ('ab' ('c' 'ef'?)*)? } +p = m.C(('ab' * ('c' * m.P'ef'^-1)^0)^-1) +s = "abcefccefc" +assert(s == p:match(s)) pi = "3.14159 26535 89793 23846 26433 83279 50288 41971 69399 37510" @@ -352,6 +356,11 @@ checkeq(t, {hi = 10, ho = 20}) t = p:match'abc' checkeq(t, {hi = 10, ho = 20, 'a', 'b', 'c'}) +-- non-string group names +p = m.Ct(m.Cg(1, print) * m.Cg(1, 23.5) * m.Cg(1, io)) +t = p:match('abcdefghij') +assert(t[print] == 'a' and t[23.5] == 'b' and t[io] == 'c') + -- test for error messages local function checkerr (msg, f, ...) @@ -388,6 +397,25 @@ p = m.P { (m.P {m.P'abc'} + 'ayz') * m.V'y'; y = m.P'x' } assert(p:match('abcx') == 5 and p:match('ayzx') == 5 and not p:match'abc') +do + -- large dynamic Cc + local lim = 2^16 - 1 + local c = 0 + local function seq (n) + if n == 1 then c = c + 1; return m.Cc(c) + else + local m = math.floor(n / 2) + return seq(m) * seq(n - m) + end + end + p = m.Ct(seq(lim)) + t = p:match('') + assert(t[lim] == lim) + checkerr("too many", function () p = p / print end) + checkerr("too many", seq, lim + 1) +end + + -- tests for non-pattern as arguments to pattern functions p = { ('a' * m.V(1))^-1 } * m.P'b' * { 'a' * m.V(2); m.V(1)^-1 } @@ -575,9 +603,9 @@ assert(not p:match(string.rep("011", 10001))) -- this grammar does need backtracking info. local lim = 10000 p = m.P{ '0' * m.V(1) + '0' } -checkerr("too many pending", m.match, p, string.rep("0", lim)) +checkerr("stack overflow", m.match, p, string.rep("0", lim)) m.setmaxstack(2*lim) -checkerr("too many pending", m.match, p, string.rep("0", lim)) +checkerr("stack overflow", m.match, p, string.rep("0", lim)) m.setmaxstack(2*lim + 4) assert(m.match(p, string.rep("0", lim)) == lim + 1) @@ -586,7 +614,7 @@ p = m.P{ ('a' * m.V(1))^0 * 'b' + 'c' } m.setmaxstack(200) assert(p:match(string.rep('a', 180) .. 'c' .. string.rep('b', 180)) == 362) -m.setmaxstack(5) -- restore original limit +m.setmaxstack(100) -- restore low limit -- tests for optional start position assert(m.match("a", "abc", 1)) @@ -718,6 +746,10 @@ t = {m.match(m.Cc(nil,nil,4) * m.Cc(nil,3) * m.Cc(nil, nil) / g / g, "")} t1 = {1,1,nil,nil,4,nil,3,nil,nil} for i=1,10 do assert(t[i] == t1[i]) end +-- bug in 0.12.2: ktable with only nil could be eliminated when joining +-- with a pattern without ktable +assert((m.P"aaa" * m.Cc(nil)):match"aaa" == nil) + t = {m.match((m.C(1) / function (x) return x, x.."x" end)^0, "abc")} checkeq(t, {"a", "ax", "b", "bx", "c", "cx"}) @@ -925,6 +957,13 @@ p = m.Cg(m.C(1) * m.C(1), "k") * m.Ct(m.Cb("k")) t = p:match("ab") checkeq(t, {"a", "b"}) +p = m.P(true) +for i = 1, 10 do p = p * m.Cg(1, i) end +for i = 1, 10 do + local p = p * m.Cb(i) + assert(p:match('abcdefghij') == string.sub('abcdefghij', i, i)) +end + t = {} function foo (p) t[#t + 1] = p; return p .. "x" end From 3a06dcf534e89a81e5bcf532e3b3cbade985bab9 Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Mon, 5 Oct 2015 10:05:36 +0800 Subject: [PATCH 04/18] update jemalloc to 4.0.3 --- 3rd/jemalloc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rd/jemalloc b/3rd/jemalloc index 3541a904..e9192eac 160000 --- a/3rd/jemalloc +++ b/3rd/jemalloc @@ -1 +1 @@ -Subproject commit 3541a904d6fb949f3f0aea05418ccce7cbd4b705 +Subproject commit e9192eacf8935e29fc62fddc2701f7942b1cc02c From 79e73d907e566b12fb69d2ad6ead02914bde7916 Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Mon, 5 Oct 2015 10:09:22 +0800 Subject: [PATCH 05/18] add target update3rd --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 98f7d1c9..e0f0b14d 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ JEMALLOC_INC := 3rd/jemalloc/include/jemalloc all : jemalloc -.PHONY : jemalloc +.PHONY : jemalloc update3rd MALLOC_STATICLIB := $(JEMALLOC_STATICLIB) @@ -39,6 +39,9 @@ $(JEMALLOC_STATICLIB) : 3rd/jemalloc/Makefile jemalloc : $(MALLOC_STATICLIB) +update3rd : + rm -rf 3rd/jemalloc && git submodule update --init + # skynet CSERVICE = snlua logger gate harbor From 8924b86ad7231e52b44d6dc8c06ab3d58d25f77e Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Thu, 8 Oct 2015 15:15:35 +0800 Subject: [PATCH 06/18] check empty group, See pr #351 --- service/multicastd.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/multicastd.lua b/service/multicastd.lua index 7bafab78..2ff1a7f0 100644 --- a/service/multicastd.lua +++ b/service/multicastd.lua @@ -67,7 +67,7 @@ end -- for remote node, call remote_publish. (call mc.unpack and skynet.tostring to convert message pointer to string) local function publish(c , source, pack, size) local group = channel[c] - if group == nil then + if group == nil or next(group) == nil then -- dead channel, delete the pack. mc.bind returns the pointer in pack local pack = mc.bind(pack, 1) mc.close(pack) From 8c1011c503f6b57b780dd08e0713efa33ee8f7e1 Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Thu, 8 Oct 2015 15:30:15 +0800 Subject: [PATCH 07/18] Add sproto:exist_type and sproto:exist_proto --- lualib/sproto.lua | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lualib/sproto.lua b/lualib/sproto.lua index 911dc877..d3ae40ad 100644 --- a/lualib/sproto.lua +++ b/lualib/sproto.lua @@ -58,6 +58,15 @@ local function querytype(self, typename) return v end +function sproto:exist_type(typename) + local v = self.__tcache[typename] + if not v then + return core.querytype(self.__cobj, typename) ~= nil + else + return true + end +end + function sproto:encode(typename, tbl) local st = querytype(self, typename) return core.encode(st, tbl) @@ -99,6 +108,15 @@ local function queryproto(self, pname) return v end +function sproto:exist_proto(pname) + local v = self.__pcache[pname] + if not v then + return core.protocol(self.__cobj, pname) ~= nil + else + return true + end +end + function sproto:request_encode(protoname, tbl) local p = queryproto(self, protoname) local request = p.request From 8dd9923cf6313a2858f0a5633ff0aa43964d8695 Mon Sep 17 00:00:00 2001 From: xjdrew Date: Thu, 8 Oct 2015 16:55:29 +0800 Subject: [PATCH 08/18] gate: application could control when to start receiving data --- service-src/service_gate.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/service-src/service_gate.c b/service-src/service_gate.c index 29eab2ea..600c4ec7 100644 --- a/service-src/service_gate.c +++ b/service-src/service_gate.c @@ -132,7 +132,12 @@ _ctrl(struct gate * g, const void * msg, int sz) { return; } if (memcmp(command,"start",i) == 0) { - skynet_socket_start(ctx, g->listen_id); + _parm(tmp, sz, i); + int uid = strtol(command , NULL, 10); + int id = hashid_lookup(&g->hash, uid); + if (id>=0) { + skynet_socket_start(ctx, uid); + } return; } if (memcmp(command, "close", i) == 0) { @@ -225,10 +230,7 @@ dispatch_socket_message(struct gate *g, const struct skynet_socket_message * mes break; } int id = hashid_lookup(&g->hash, message->id); - if (id>=0) { - struct connection *c = &g->conn[id]; - _report(g, "%d open %d %s:0",message->id,message->id,c->remote_name); - } else { + if (id<0) { skynet_error(ctx, "Close unknown connection %d", message->id); skynet_socket_close(ctx, message->id); } @@ -259,7 +261,8 @@ dispatch_socket_message(struct gate *g, const struct skynet_socket_message * mes c->id = message->ud; memcpy(c->remote_name, message+1, sz); c->remote_name[sz] = '\0'; - skynet_socket_start(ctx, message->ud); + _report(g, "%d open %d %s:0",c->id, c->id, c->remote_name); + skynet_error(ctx, "socket open: %x", c->id); } break; case SKYNET_SOCKET_TYPE_WARNING: @@ -327,6 +330,7 @@ start_listen(struct gate *g, char * listen_addr) { if (g->listen_id < 0) { return 1; } + skynet_socket_start(ctx, g->listen_id); return 0; } From 515326dadcfb1b9c922bbdff4c99110e19f550a6 Mon Sep 17 00:00:00 2001 From: xjdrew Date: Sat, 10 Oct 2015 18:39:42 +0800 Subject: [PATCH 09/18] bugfix: remove Wformat warning --- service-src/service_gate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service-src/service_gate.c b/service-src/service_gate.c index 600c4ec7..71ab1a64 100644 --- a/service-src/service_gate.c +++ b/service-src/service_gate.c @@ -344,7 +344,7 @@ gate_init(struct gate *g , struct skynet_context * ctx, char * parm) { char binding[sz]; int client_tag = 0; char header; - int n = sscanf(parm, "%c %s %s %d %d %d", &header, watchdog, binding, &client_tag, &max); + int n = sscanf(parm, "%c %s %s %d %d", &header, watchdog, binding, &client_tag, &max); if (n<4) { skynet_error(ctx, "Invalid gate parm %s",parm); return 1; From 878110f9f75fe0ddb179077bcf409d9fbc34de44 Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Mon, 12 Oct 2015 12:29:19 +0800 Subject: [PATCH 10/18] add codecache.mode() --- 3rd/lua/lauxlib.c | 50 +++++++++++++++++++++++++++++++++++++ service-src/service_snlua.c | 1 + 2 files changed, 51 insertions(+) diff --git a/3rd/lua/lauxlib.c b/3rd/lua/lauxlib.c index e4d79955..49657027 100644 --- a/3rd/lua/lauxlib.c +++ b/3rd/lua/lauxlib.c @@ -1040,13 +1040,62 @@ save(const char *key, const void * proto) { return result; } +#define CACHE_OFF 0 +#define CACHE_EXIST 1 +#define CACHE_ON 2 + +static int cache_key = 0; + +static int cache_level(lua_State *L) { + int t = lua_rawgetp(L, LUA_REGISTRYINDEX, &cache_key); + int r = lua_tointeger(L, -1); + lua_pop(L,1); + if (t == LUA_TNUMBER) { + return r; + } + return CACHE_ON; +} + +static int cache_mode(lua_State *L) { + static const char * lst[] = { + "OFF", + "EXIST", + "ON", + NULL, + }; + if (lua_isnoneornil(L,1)) { + int t = lua_rawgetp(L, LUA_REGISTRYINDEX, &cache_key); + int r = lua_tointeger(L, -1); + if (t == LUA_TNUMBER) { + if (r < 0 || r >= CACHE_ON) { + r = CACHE_ON; + } + } else { + r = CACHE_ON; + } + lua_pushstring(L, lst[r]); + return 1; + } + int t = luaL_checkoption(L, 1, "OFF" , lst); + lua_pushinteger(L, t); + lua_rawsetp(L, LUA_REGISTRYINDEX, &cache_key); + return 0; +} + LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename, const char *mode) { + int level = cache_level(L); + if (level == CACHE_OFF) { + return luaL_loadfilex_(L, filename, mode); + } const void * proto = load(filename); if (proto) { lua_clonefunction(L, proto); return LUA_OK; } + if (level == CACHE_EXIST) { + return luaL_loadfilex_(L, filename, mode); + } lua_State * eL = luaL_newstate(); if (eL == NULL) { lua_pushliteral(L, "New state failed"); @@ -1083,6 +1132,7 @@ cache_clear(lua_State *L) { LUAMOD_API int luaopen_cache(lua_State *L) { luaL_Reg l[] = { { "clear", cache_clear }, + { "mode", cache_mode }, { NULL, NULL }, }; luaL_newlib(L,l); diff --git a/service-src/service_snlua.c b/service-src/service_snlua.c index 89e607f6..20440780 100644 --- a/service-src/service_snlua.c +++ b/service-src/service_snlua.c @@ -30,6 +30,7 @@ static int codecache(lua_State *L) { luaL_Reg l[] = { { "clear", cleardummy }, + { "mode", cleardummy }, { NULL, NULL }, }; luaL_newlib(L,l); From d7e4e43a1b1cd73e6d40369265766084d9deaee3 Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Mon, 12 Oct 2015 13:07:09 +0800 Subject: [PATCH 11/18] use spinlock macro --- 3rd/lua/lauxlib.c | 21 ++++++++++----------- skynet-src/spinlock.h | 1 + 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/3rd/lua/lauxlib.c b/3rd/lua/lauxlib.c index 49657027..dec81e8a 100644 --- a/3rd/lua/lauxlib.c +++ b/3rd/lua/lauxlib.c @@ -972,29 +972,28 @@ LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) { // use clonefunction -#define LOCK(q) while (__sync_lock_test_and_set(&(q)->lock,1)) {} -#define UNLOCK(q) __sync_lock_release(&(q)->lock); +#include "spinlock.h" struct codecache { - int lock; + struct spinlock lock; lua_State *L; }; -static struct codecache CC = { 0 , NULL }; +static struct codecache CC; static void clearcache() { if (CC.L == NULL) return; - LOCK(&CC) + SPIN_LOCK(&CC) lua_close(CC.L); CC.L = luaL_newstate(); - UNLOCK(&CC) + SPIN_UNLOCK(&CC) } static void init() { - CC.lock = 0; + SPIN_INIT(&CC); CC.L = luaL_newstate(); } @@ -1002,13 +1001,13 @@ static const void * load(const char *key) { if (CC.L == NULL) return NULL; - LOCK(&CC) + SPIN_LOCK(&CC) lua_State *L = CC.L; lua_pushstring(L, key); lua_rawget(L, LUA_REGISTRYINDEX); const void * result = lua_touserdata(L, -1); lua_pop(L, 1); - UNLOCK(&CC) + SPIN_UNLOCK(&CC) return result; } @@ -1018,7 +1017,7 @@ save(const char *key, const void * proto) { lua_State *L; const void * result = NULL; - LOCK(&CC) + SPIN_LOCK(&CC) if (CC.L == NULL) { init(); L = CC.L; @@ -1036,7 +1035,7 @@ save(const char *key, const void * proto) { lua_pop(L,2); } } - UNLOCK(&CC) + SPIN_UNLOCK(&CC) return result; } diff --git a/skynet-src/spinlock.h b/skynet-src/spinlock.h index d9744c3f..514546f4 100644 --- a/skynet-src/spinlock.h +++ b/skynet-src/spinlock.h @@ -34,6 +34,7 @@ spinlock_unlock(struct spinlock *lock) { static inline void spinlock_destroy(struct spinlock *lock) { + (void) lock; } #else From d2f2e299d527a0ab19a9c69a58ebfcd73db63e47 Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Mon, 12 Oct 2015 14:40:42 +0800 Subject: [PATCH 12/18] call socket.abandon while auth error, see issue #355 --- lualib/snax/loginserver.lua | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lualib/snax/loginserver.lua b/lualib/snax/loginserver.lua index 01b2d49b..dfaa3ebd 100644 --- a/lualib/snax/loginserver.lua +++ b/lualib/snax/loginserver.lua @@ -49,7 +49,6 @@ end local function launch_slave(auth_handler) local function auth(fd, addr) - fd = assert(tonumber(fd)) skynet.error(string.format("connect from %s (fd = %d)", addr, fd)) socket.start(fd) @@ -84,11 +83,11 @@ local function launch_slave(auth_handler) local ok, server, uid = pcall(auth_handler,token) - socket.abandon(fd) return ok, server, uid, secret end - local function ret_pack(ok, err, ...) + local function ret_pack(fd, ok, err, ...) + socket.abandon(fd) if ok then skynet.ret(skynet.pack(err, ...)) else @@ -100,8 +99,12 @@ local function launch_slave(auth_handler) end end - skynet.dispatch("lua", function(_,_,...) - ret_pack(pcall(auth, ...)) + skynet.dispatch("lua", function(_,_,fd,...) + if type(fd) ~= "number" then + skynet.ret(skynet.pack(false, "invalid fd type")) + else + ret_pack(fd,pcall(auth, fd, ...)) + end end) end From 9aaa35ef142da0d6e9ab0c6a2326ee8442716d6b Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Wed, 14 Oct 2015 15:24:51 +0800 Subject: [PATCH 13/18] avoid lua stack overflow --- lualib-src/lua-bson.c | 2 ++ skynet-src/skynet_timer.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lualib-src/lua-bson.c b/lualib-src/lua-bson.c index 0fc26985..bcd44162 100644 --- a/lualib-src/lua-bson.c +++ b/lualib-src/lua-bson.c @@ -408,6 +408,7 @@ bson_numstr( char *str, unsigned int i ) { static void pack_dict(lua_State *L, struct bson *b, bool isarray) { + luaL_checkstack(L, 16, NULL); // reserve enough stack space to pack table int length = reserve_length(b); lua_pushnil(L); while(lua_next(L,-2) != 0) { @@ -495,6 +496,7 @@ make_object(lua_State *L, int type, const void * ptr, size_t len) { static void unpack_dict(lua_State *L, struct bson_reader *br, bool array) { + luaL_checkstack(L, 16, NULL); // reserve enough stack space to unpack table int sz = read_int32(L, br); const void * bytes = read_bytes(L, br, sz-5); struct bson_reader t = { bytes, sz-5 }; diff --git a/skynet-src/skynet_timer.c b/skynet-src/skynet_timer.c index c9a113ae..1f366b85 100644 --- a/skynet-src/skynet_timer.c +++ b/skynet-src/skynet_timer.c @@ -208,7 +208,7 @@ timer_create_timer() { int skynet_timeout(uint32_t handle, int time, int session) { - if (time == 0) { + if (time <= 0) { struct skynet_message message; message.source = 0; message.session = session; From 7486e5323287765b14e04b22412b6aa93e5f047a Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Wed, 14 Oct 2015 15:44:09 +0800 Subject: [PATCH 14/18] avoid circular reference while encodeing bson --- lualib-src/lua-bson.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/lualib-src/lua-bson.c b/lualib-src/lua-bson.c index bcd44162..7319a0dd 100644 --- a/lualib-src/lua-bson.c +++ b/lualib-src/lua-bson.c @@ -12,6 +12,8 @@ #define DEFAULT_CAP 64 #define MAX_NUMBER 1024 +// avoid circular reference while encodeing +#define MAX_DEPTH 128 #define BSON_REAL 1 #define BSON_STRING 2 @@ -236,7 +238,7 @@ write_double(struct bson *b, lua_Number d) { } } -static void pack_dict(lua_State *L, struct bson *b, bool array); +static void pack_dict(lua_State *L, struct bson *b, bool array, int depth); static inline void append_key(struct bson *bs, int type, const char *key, size_t sz) { @@ -268,7 +270,7 @@ append_number(struct bson *bs, lua_State *L, const char *key, size_t sz) { } static void -append_table(struct bson *bs, lua_State *L, const char *key, size_t sz) { +append_table(struct bson *bs, lua_State *L, const char *key, size_t sz, int depth) { size_t len = lua_rawlen(L, -1); bool isarray = false; if (len > 0) { @@ -284,7 +286,7 @@ append_table(struct bson *bs, lua_State *L, const char *key, size_t sz) { } else { append_key(bs, BSON_DOCUMENT, key, sz); } - pack_dict(L, bs, isarray); + pack_dict(L, bs, isarray, depth); } static void @@ -297,7 +299,7 @@ write_binary(struct bson *b, const void * buffer, size_t sz) { } static void -append_one(struct bson *bs, lua_State *L, const char *key, size_t sz) { +append_one(struct bson *bs, lua_State *L, const char *key, size_t sz, int depth) { int vt = lua_type(L,-1); switch(vt) { case LUA_TNUMBER: @@ -385,7 +387,7 @@ append_one(struct bson *bs, lua_State *L, const char *key, size_t sz) { break; } case LUA_TTABLE: - append_table(bs, L, key, sz); + append_table(bs, L, key, sz, depth+1); break; case LUA_TBOOLEAN: append_key(bs, BSON_BOOLEAN, key, sz); @@ -407,7 +409,10 @@ bson_numstr( char *str, unsigned int i ) { } static void -pack_dict(lua_State *L, struct bson *b, bool isarray) { +pack_dict(lua_State *L, struct bson *b, bool isarray, int depth) { + if (depth > MAX_DEPTH) { + luaL_error(L, "Too depth while encoding bson"); + } luaL_checkstack(L, 16, NULL); // reserve enough stack space to pack table int length = reserve_length(b); lua_pushnil(L); @@ -424,7 +429,7 @@ pack_dict(lua_State *L, struct bson *b, bool isarray) { sz = bson_numstr(numberkey, (unsigned int)lua_tointeger(L,-2)-1); key = numberkey; - append_one(b, L, key, sz); + append_one(b, L, key, sz, depth); lua_pop(L,1); } else { switch(kt) { @@ -433,12 +438,12 @@ pack_dict(lua_State *L, struct bson *b, bool isarray) { lua_pushvalue(L,-2); lua_insert(L,-2); key = lua_tolstring(L,-2,&sz); - append_one(b, L, key, sz); + append_one(b, L, key, sz, depth); lua_pop(L,2); break; case LUA_TSTRING: key = lua_tolstring(L,-2,&sz); - append_one(b, L, key, sz); + append_one(b, L, key, sz, depth); lua_pop(L,1); break; default: @@ -452,7 +457,7 @@ pack_dict(lua_State *L, struct bson *b, bool isarray) { } static void -pack_ordered_dict(lua_State *L, struct bson *b, int n) { +pack_ordered_dict(lua_State *L, struct bson *b, int n, int depth) { int length = reserve_length(b); int i; for (i=0;i Date: Wed, 14 Oct 2015 20:12:30 +0800 Subject: [PATCH 15/18] bugfix: socketchannel order mode may blocked. (used by redis driver) --- lualib/dns.lua | 2 +- lualib/skynet.lua | 4 +-- lualib/socket.lua | 6 ++-- lualib/socketchannel.lua | 74 ++++++++++++++++++++++------------------ 4 files changed, 46 insertions(+), 40 deletions(-) diff --git a/lualib/dns.lua b/lualib/dns.lua index 35e38084..e349699f 100644 --- a/lualib/dns.lua +++ b/lualib/dns.lua @@ -265,7 +265,7 @@ local function suspend(tid, name, qtype) co = coroutine.running(), } request_pool[tid] = req - skynet.wait() + skynet.wait(req.co) local answers = request_pool[tid].answers request_pool[tid] = nil assert(answers, "no ip") diff --git a/lualib/skynet.lua b/lualib/skynet.lua index 554d8ff8..c20efaa2 100644 --- a/lualib/skynet.lua +++ b/lualib/skynet.lua @@ -275,10 +275,10 @@ function skynet.yield() return skynet.sleep(0) end -function skynet.wait() +function skynet.wait(co) local session = c.genid() local ret, msg = coroutine_yield("SLEEP", session) - local co = coroutine.running() + co = co or coroutine.running() sleep_session[co] = nil session_id_coroutine[session] = nil end diff --git a/lualib/socket.lua b/lualib/socket.lua index 7f1d603b..58fe2678 100644 --- a/lualib/socket.lua +++ b/lualib/socket.lua @@ -30,7 +30,7 @@ end local function suspend(s) assert(not s.co) s.co = coroutine.running() - skynet.wait() + skynet.wait(s.co) -- wakeup closing corouting every time suspend, -- because socket.close() will wait last socket buffer operation before clear the buffer. if s.closing then @@ -232,7 +232,7 @@ function socket.close(id) -- wait reading coroutine read the buffer. assert(not s.closing) s.closing = coroutine.running() - skynet.wait() + skynet.wait(s.closing) else suspend(s) end @@ -361,7 +361,7 @@ function socket.lock(id) else local co = coroutine.running() table.insert(lock_set, co) - skynet.wait() + skynet.wait(co) end end diff --git a/lualib/socketchannel.lua b/lualib/socketchannel.lua index 9ff5d451..547b9f87 100644 --- a/lualib/socketchannel.lua +++ b/lualib/socketchannel.lua @@ -115,8 +115,17 @@ local function dispatch_by_session(self) end end +local wait_response + local function pop_response(self) - return table.remove(self.__request, 1), table.remove(self.__thread, 1) + while true do + local func,co = table.remove(self.__request, 1), table.remove(self.__thread, 1) + if func then + return func, co + end + wait_response = coroutine.running() + skynet.wait(wait_response) + end end local function push_response(self, response, co) @@ -127,46 +136,43 @@ local function push_response(self, response, co) -- response is a function, push it to __request table.insert(self.__request, response) table.insert(self.__thread, co) + if wait_response then + skynet.wakeup(wait_response) + wait_response = nil + end end end local function dispatch_by_order(self) while self.__sock do local func, co = pop_response(self) - if func == nil then - if not socket.block(self.__sock[1]) then - close_channel_socket(self) - wakeup_all(self) + local ok, result_ok, result_data, padding = pcall(func, self.__sock) + if ok then + if padding and result_ok then + -- if padding is true, wait for next result_data + -- self.__result_data[co] is a table + local result = self.__result_data[co] or {} + self.__result_data[co] = result + table.insert(result, result_data) + else + self.__result[co] = result_ok + if result_ok and self.__result_data[co] then + table.insert(self.__result_data[co], result_data) + else + self.__result_data[co] = result_data + end + skynet.wakeup(co) end else - local ok, result_ok, result_data, padding = pcall(func, self.__sock) - if ok then - if padding and result_ok then - -- if padding is true, wait for next result_data - -- self.__result_data[co] is a table - local result = self.__result_data[co] or {} - self.__result_data[co] = result - table.insert(result, result_data) - else - self.__result[co] = result_ok - if result_ok and self.__result_data[co] then - table.insert(self.__result_data[co], result_data) - else - self.__result_data[co] = result_data - end - skynet.wakeup(co) - end - else - close_channel_socket(self) - local errmsg - if result_ok ~= socket_error then - errmsg = result_ok - end - self.__result[co] = socket_error - self.__result_data[co] = errmsg - skynet.wakeup(co) - wakeup_all(self, errmsg) + close_channel_socket(self) + local errmsg + if result_ok ~= socket_error then + errmsg = result_ok end + self.__result[co] = socket_error + self.__result_data[co] = errmsg + skynet.wakeup(co) + wakeup_all(self, errmsg) end end end @@ -288,7 +294,7 @@ local function block_connect(self, once) -- connecting in other coroutine local co = coroutine.running() table.insert(self.__connecting, co) - skynet.wait() + skynet.wait(co) else self.__connecting[1] = true try_connect(self, once) @@ -319,7 +325,7 @@ end local function wait_for_response(self, response) local co = coroutine.running() push_response(self, response, co) - skynet.wait() + skynet.wait(co) local result = self.__result[co] self.__result[co] = nil From bab91a306753174d2e95cfca133b7ff8f78ea642 Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Thu, 15 Oct 2015 14:01:50 +0800 Subject: [PATCH 16/18] bugfix: don't use global wait_response --- lualib/socketchannel.lua | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/lualib/socketchannel.lua b/lualib/socketchannel.lua index 547b9f87..0452cc15 100644 --- a/lualib/socketchannel.lua +++ b/lualib/socketchannel.lua @@ -115,16 +115,14 @@ local function dispatch_by_session(self) end end -local wait_response - local function pop_response(self) while true do local func,co = table.remove(self.__request, 1), table.remove(self.__thread, 1) if func then return func, co end - wait_response = coroutine.running() - skynet.wait(wait_response) + self.wait_response = coroutine.running() + skynet.wait(self.wait_response) end end @@ -136,9 +134,9 @@ local function push_response(self, response, co) -- response is a function, push it to __request table.insert(self.__request, response) table.insert(self.__thread, co) - if wait_response then - skynet.wakeup(wait_response) - wait_response = nil + if self.wait_response then + skynet.wakeup(self.wait_response) + self.wait_response = nil end end end From 2d27df6f4607d637b4773977b385efeb2db4c2f6 Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Thu, 15 Oct 2015 14:08:01 +0800 Subject: [PATCH 17/18] change name --- lualib/socketchannel.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lualib/socketchannel.lua b/lualib/socketchannel.lua index 0452cc15..7e7a0f6b 100644 --- a/lualib/socketchannel.lua +++ b/lualib/socketchannel.lua @@ -121,8 +121,8 @@ local function pop_response(self) if func then return func, co end - self.wait_response = coroutine.running() - skynet.wait(self.wait_response) + self.__wait_response = coroutine.running() + skynet.wait(self.__wait_response) end end @@ -134,9 +134,9 @@ local function push_response(self, response, co) -- response is a function, push it to __request table.insert(self.__request, response) table.insert(self.__thread, co) - if self.wait_response then - skynet.wakeup(self.wait_response) - self.wait_response = nil + if self.__wait_response then + skynet.wakeup(self.__wait_response) + self.__wait_response = nil end end end From 26cbebfcfd0051bdb17757a96df7509f96fefeab Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Wed, 21 Oct 2015 12:58:57 +0800 Subject: [PATCH 18/18] verify callback overflow --- lualib-src/sproto/sproto.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lualib-src/sproto/sproto.c b/lualib-src/sproto/sproto.c index b5d61ea6..ec77441b 100644 --- a/lualib-src/sproto/sproto.c +++ b/lualib-src/sproto/sproto.c @@ -677,6 +677,7 @@ encode_object(sproto_callback cb, struct sproto_arg *args, uint8_t *data, int si args->value = data+SIZEOF_LENGTH; args->length = size-SIZEOF_LENGTH; sz = cb(args); + assert(sz <= size-SIZEOF_LENGTH); // verify buffer overflow if (sz <= 0) return sz; if (args->type == SPROTO_TSTRING) {