From d4023c8b6314b4f8017c6bf702875ce16f87b84b Mon Sep 17 00:00:00 2001
From: sanikoyes
Date: Thu, 2 Jul 2015 16:25:10 +0800
Subject: [PATCH 01/97] fix invalid fd after reconnected, used in unpack_f
---
examples/login/client.lua | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/examples/login/client.lua b/examples/login/client.lua
index 4180e7a7..f7c48018 100644
--- a/examples/login/client.lua
+++ b/examples/login/client.lua
@@ -131,7 +131,7 @@ local text = "echo"
local index = 1
print("connect")
-local fd = assert(socket.connect("127.0.0.1", 8888))
+fd = assert(socket.connect("127.0.0.1", 8888))
last = ""
local handshake = string.format("%s@%s#%s:%d", crypt.base64encode(token.user), crypt.base64encode(token.server),crypt.base64encode(subid) , index)
@@ -151,7 +151,7 @@ socket.close(fd)
index = index + 1
print("connect again")
-local fd = assert(socket.connect("127.0.0.1", 8888))
+fd = assert(socket.connect("127.0.0.1", 8888))
last = ""
local handshake = string.format("%s@%s#%s:%d", crypt.base64encode(token.user), crypt.base64encode(token.server),crypt.base64encode(subid) , index)
From 55cf9375fc11e816ff1bdc5746a7aaa49591839b Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Fri, 3 Jul 2015 10:58:40 +0800
Subject: [PATCH 02/97] asterisk(*) should be once or not at all
---
lualib/sprotoparser.lua | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lualib/sprotoparser.lua b/lualib/sprotoparser.lua
index 7b0b04e2..03524ac0 100644
--- a/lualib/sprotoparser.lua
+++ b/lualib/sprotoparser.lua
@@ -81,7 +81,7 @@ end
local typedef = P {
"ALL",
- FIELD = namedpat("field", (name * blanks * tag * blank0 * ":" * blank0 * (C"*")^0 * typename * mainkey^0)),
+ FIELD = namedpat("field", (name * blanks * tag * blank0 * ":" * blank0 * (C"*")^-1 * typename * mainkey^0)),
STRUCT = P"{" * multipat(V"FIELD" + V"TYPE") * P"}",
TYPE = namedpat("type", P"." * name * blank0 * V"STRUCT" ),
SUBPROTO = Ct((C"request" + C"response") * blanks * (typename + V"STRUCT")),
From 86bbc9c7011cce8966d192d14ee9c8c8667c35ad Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Tue, 7 Jul 2015 12:11:16 +0800
Subject: [PATCH 03/97] off by 1 error
---
skynet-src/socket_server.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/skynet-src/socket_server.c b/skynet-src/socket_server.c
index 1b480da7..78f9b47b 100644
--- a/skynet-src/socket_server.c
+++ b/skynet-src/socket_server.c
@@ -1265,7 +1265,7 @@ send_request(struct socket_server *ss, struct request_package *request, char typ
static int
open_request(struct socket_server *ss, struct request_package *req, uintptr_t opaque, const char *addr, int port) {
int len = strlen(addr);
- if (len + sizeof(req->u.open) > 256) {
+ if (len + sizeof(req->u.open) >= 256) {
fprintf(stderr, "socket-server : Invalid addr %s.\n",addr);
return -1;
}
From ea2437e138a92a0182f19a3e88c431cf2a985c5b Mon Sep 17 00:00:00 2001
From: sanikoyes
Date: Thu, 9 Jul 2015 18:07:32 +0800
Subject: [PATCH 04/97] lunpack optimize, do not unpack twice if r <= osz
---
lualib-src/sproto/lsproto.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/lualib-src/sproto/lsproto.c b/lualib-src/sproto/lsproto.c
index 50a05f67..16eaa022 100644
--- a/lualib-src/sproto/lsproto.c
+++ b/lualib-src/sproto/lsproto.c
@@ -487,10 +487,10 @@ lunpack(lua_State *L) {
return luaL_error(L, "Invalid unpack stream");
if (r > osz) {
output = expand_buffer(L, osz, r);
+ r = sproto_unpack(buffer, sz, output, r);
+ if (r < 0)
+ return luaL_error(L, "Invalid unpack stream");
}
- r = sproto_unpack(buffer, sz, output, r);
- if (r < 0)
- return luaL_error(L, "Invalid unpack stream");
lua_pushlstring(L, output, r);
return 1;
}
From d9ad981c8c3f55965327f7869038dad0a026cfa0 Mon Sep 17 00:00:00 2001
From: cxj
Date: Fri, 10 Jul 2015 20:21:07 +0800
Subject: [PATCH 05/97] sproto optimize, malloc newchunk and return directly if
sz >= CHUNK_SIZE in pool_alloc, do not replace current chunk if sz >=
p->current_used in pool_alloc, more safety checking
---
lualib-src/sproto/sproto.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/lualib-src/sproto/sproto.c b/lualib-src/sproto/sproto.c
index 8324d64f..b5d61ea6 100644
--- a/lualib-src/sproto/sproto.c
+++ b/lualib-src/sproto/sproto.c
@@ -83,7 +83,7 @@ static void *
pool_alloc(struct pool *p, size_t sz) {
// align by 8
sz = (sz + 7) & ~7;
- if (sz > CHUNK_SIZE) {
+ if (sz >= CHUNK_SIZE) {
return pool_newchunk(p, sz);
}
if (p->current == NULL) {
@@ -97,7 +97,7 @@ pool_alloc(struct pool *p, size_t sz) {
return ret;
}
- if (sz > p->current_used) {
+ if (sz >= p->current_used) {
return pool_newchunk(p, sz);
} else {
void * ret = pool_newchunk(p, CHUNK_SIZE);
@@ -305,7 +305,7 @@ import_type(struct sproto *s, struct sproto_type *t, const uint8_t * stream) {
if (stream == NULL)
return NULL;
tag = f->tag;
- if (tag < last)
+ if (tag <= last)
return NULL; // tag must in ascending order
if (tag > last+1) {
++maxn;
@@ -394,7 +394,7 @@ create_from_bundle(struct sproto *s, const uint8_t * stream, size_t sz) {
const uint8_t * protocoldata = NULL;
int fn = struct_field(stream, sz);
int i;
- if (fn < 0)
+ if (fn < 0 || fn > 2)
return NULL;
stream += SIZEOF_HEADER;
From 538414408d47af80b29e370db6b512807552b0c4 Mon Sep 17 00:00:00 2001
From: cxj
Date: Mon, 13 Jul 2015 13:04:09 +0800
Subject: [PATCH 06/97] sharedata serialization bugfix
---
examples/share.lua | 2 +-
lualib-src/lua-seri.c | 4 +++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/examples/share.lua b/examples/share.lua
index 2721d480..8bc4b497 100644
--- a/examples/share.lua
+++ b/examples/share.lua
@@ -43,7 +43,7 @@ skynet.start(function()
for k,v in pairs(nobj) do
skynet.error(string.format("nobj[%s]=%s", k,v))
end
- for k,v in ipairs(nobj) do
+ for k,v in ipairs(nobj.b) do
skynet.error(string.format("nobj.b[%d]=%s", k,v))
end
diff --git a/lualib-src/lua-seri.c b/lualib-src/lua-seri.c
index 0db2267d..c0761bd5 100644
--- a/lualib-src/lua-seri.c
+++ b/lualib-src/lua-seri.c
@@ -266,8 +266,10 @@ wb_table_metapairs(lua_State *L, struct write_block *wb, int index, int depth) {
lua_copy(L, -5, -3);
lua_call(L, 2, 2);
int type = lua_type(L, -2);
- if (type == LUA_TNIL)
+ if (type == LUA_TNIL) {
+ lua_pop(L, 4);
break;
+ }
pack_one(L, wb, -2, depth);
pack_one(L, wb, -1, depth);
lua_pop(L, 1);
From a0ecd512307f074164f3c0580b444262ea7a48bb Mon Sep 17 00:00:00 2001
From: LiBei <252608386@qq.com>
Date: Tue, 21 Jul 2015 11:12:55 +0800
Subject: [PATCH 07/97] Update cdummy.lua
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
误定义全局变量
---
service/cdummy.lua | 1 +
1 file changed, 1 insertion(+)
diff --git a/service/cdummy.lua b/service/cdummy.lua
index 62865222..7926e35e 100644
--- a/service/cdummy.lua
+++ b/service/cdummy.lua
@@ -4,6 +4,7 @@ require "skynet.manager" -- import skynet.launch, ...
local globalname = {}
local queryname = {}
local harbor = {}
+local harbor_service
skynet.register_protocol {
name = "harbor",
From 3f91484791e6be1610633f70b72d1725d803faf4 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Tue, 21 Jul 2015 11:31:27 +0800
Subject: [PATCH 08/97] user log service
---
examples/config.userlog | 18 ++++++++++++++++++
examples/userlog.lua | 15 +++++++++++++++
2 files changed, 33 insertions(+)
create mode 100644 examples/config.userlog
create mode 100644 examples/userlog.lua
diff --git a/examples/config.userlog b/examples/config.userlog
new file mode 100644
index 00000000..97bef6ef
--- /dev/null
+++ b/examples/config.userlog
@@ -0,0 +1,18 @@
+root = "./"
+thread = 8
+logger = "userlog"
+logservice = "snlua"
+logpath = "."
+harbor = 1
+address = "127.0.0.1:2526"
+master = "127.0.0.1:2013"
+start = "main" -- main script
+bootstrap = "snlua bootstrap" -- The service for bootstrap
+standalone = "0.0.0.0:2013"
+luaservice = root.."service/?.lua;"..root.."test/?.lua;"..root.."examples/?.lua"
+lualoader = "lualib/loader.lua"
+-- preload = "./examples/preload.lua" -- run preload.lua before every lua service run
+snax = root.."examples/?.lua;"..root.."test/?.lua"
+-- snax_interface_g = "snax_g"
+cpath = root.."cservice/?.so"
+-- daemon = "./skynet.pid"
diff --git a/examples/userlog.lua b/examples/userlog.lua
new file mode 100644
index 00000000..55aa0952
--- /dev/null
+++ b/examples/userlog.lua
@@ -0,0 +1,15 @@
+local skynet = require "skynet"
+require "skynet.manager"
+
+skynet.register_protocol {
+ name = "text",
+ id = skynet.PTYPE_TEXT,
+ unpack = skynet.tostring,
+ dispatch = function(_, address, msg)
+ print(string.format("%x(%.2f): %s", address, skynet.time(), msg))
+ end
+}
+
+skynet.start(function()
+ skynet.register ".logger"
+end)
\ No newline at end of file
From 4ebb139c2b930cf0054a6c9914efd958e5d2c627 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Wed, 22 Jul 2015 15:52:26 +0800
Subject: [PATCH 09/97] bugfix: free message when cluster not connected
---
lualib-src/lua-cluster.c | 3 ++-
service/clusterd.lua | 7 +++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/lualib-src/lua-cluster.c b/lualib-src/lua-cluster.c
index c4875070..586f74bf 100644
--- a/lualib-src/lua-cluster.c
+++ b/lualib-src/lua-cluster.c
@@ -74,8 +74,9 @@ lpackrequest(lua_State *L) {
return luaL_error(L, "Invalid request message");
}
size_t sz = (size_t)luaL_checkinteger(L,4);
- int session = luaL_checkinteger(L,2);
+ int session = luaL_optinteger(L,2,1); // new connection start with 1
if (session <= 0) {
+ skynet_free(msg);
return luaL_error(L, "Invalid request session %d", session);
}
int addr_type = lua_type(L,1);
diff --git a/service/clusterd.lua b/service/clusterd.lua
index 12c4c4e7..3805be25 100644
--- a/service/clusterd.lua
+++ b/service/clusterd.lua
@@ -24,7 +24,6 @@ local function open_channel(t, key)
}
assert(c:connect(true))
t[key] = c
- node_session[key] = 1
return c
end
@@ -63,11 +62,11 @@ function command.listen(source, addr, port)
end
local function send_request(source, node, addr, msg, sz)
- local request
- local c = node_channel[node]
local session = node_session[node]
-- msg is a local pointer, cluster.packrequest will free it
- request, node_session[node] = cluster.packrequest(addr, session , msg, sz)
+ local request, new_session = cluster.packrequest(addr, session, msg, sz)
+ local c = node_channel[node]
+ node_session[node] = new_session
return c:request(request, session)
end
From 588c4a350800b3676e23cbcf6ffef2a34dd000ea Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Wed, 22 Jul 2015 16:49:25 +0800
Subject: [PATCH 10/97] bugfix
---
lualib-src/lua-cluster.c | 2 +-
service/clusterd.lua | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/lualib-src/lua-cluster.c b/lualib-src/lua-cluster.c
index 586f74bf..e9d9e142 100644
--- a/lualib-src/lua-cluster.c
+++ b/lualib-src/lua-cluster.c
@@ -74,7 +74,7 @@ lpackrequest(lua_State *L) {
return luaL_error(L, "Invalid request message");
}
size_t sz = (size_t)luaL_checkinteger(L,4);
- int session = luaL_optinteger(L,2,1); // new connection start with 1
+ int session = luaL_checkinteger(L,2);
if (session <= 0) {
skynet_free(msg);
return luaL_error(L, "Invalid request session %d", session);
diff --git a/service/clusterd.lua b/service/clusterd.lua
index 3805be25..b0ee6335 100644
--- a/service/clusterd.lua
+++ b/service/clusterd.lua
@@ -62,7 +62,7 @@ function command.listen(source, addr, port)
end
local function send_request(source, node, addr, msg, sz)
- local session = node_session[node]
+ local session = node_session[node] or 1
-- msg is a local pointer, cluster.packrequest will free it
local request, new_session = cluster.packrequest(addr, session, msg, sz)
local c = node_channel[node]
From 39f9a96b6c3c8276d715d8a921f17767efe1dfb5 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Thu, 23 Jul 2015 16:47:35 +0800
Subject: [PATCH 11/97] add cmemory.info() returns a table of c memory info
---
lualib-src/lua-memory.c | 1 +
service/cmemory.lua | 6 +++++-
skynet-src/malloc_hook.c | 15 +++++++++++++++
skynet-src/malloc_hook.h | 2 ++
4 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/lualib-src/lua-memory.c b/lualib-src/lua-memory.c
index 17e7cd40..67a3acf6 100644
--- a/lualib-src/lua-memory.c
+++ b/lualib-src/lua-memory.c
@@ -42,6 +42,7 @@ luaopen_memory(lua_State *L) {
{ "block", lblock },
{ "dumpinfo", ldumpinfo },
{ "dump", ldump },
+ { "info", dump_mem_lua },
{ NULL, NULL },
};
diff --git a/service/cmemory.lua b/service/cmemory.lua
index 06627ae3..e33eb42f 100644
--- a/service/cmemory.lua
+++ b/service/cmemory.lua
@@ -2,7 +2,11 @@ local skynet = require "skynet"
local memory = require "memory"
memory.dumpinfo()
-memory.dump()
+--memory.dump()
+local info = memory.info()
+for k,v in pairs(info) do
+ print(string.format(":%08x %gK",k,v/1024))
+end
print("Total memory:", memory.total())
print("Total block:", memory.block())
diff --git a/skynet-src/malloc_hook.c b/skynet-src/malloc_hook.c
index 9b3949a6..d9ad6f32 100644
--- a/skynet-src/malloc_hook.c
+++ b/skynet-src/malloc_hook.c
@@ -2,6 +2,7 @@
#include
#include
#include
+#include
#include "malloc_hook.h"
#include "skynet.h"
@@ -224,3 +225,17 @@ skynet_lalloc(void *ud, void *ptr, size_t osize, size_t nsize) {
return skynet_realloc(ptr, nsize);
}
}
+
+int
+dump_mem_lua(lua_State *L) {
+ int i;
+ lua_newtable(L);
+ for(i=0; ihandle != 0 && data->allocated != 0) {
+ lua_pushinteger(L, data->allocated);
+ lua_rawseti(L, -2, (lua_Integer)data->handle);
+ }
+ }
+ return 1;
+}
diff --git a/skynet-src/malloc_hook.h b/skynet-src/malloc_hook.h
index d35551d1..03339556 100644
--- a/skynet-src/malloc_hook.h
+++ b/skynet-src/malloc_hook.h
@@ -2,6 +2,7 @@
#define SKYNET_MALLOC_HOOK_H
#include
+#include
extern size_t malloc_used_memory(void);
extern size_t malloc_memory_block(void);
@@ -9,6 +10,7 @@ extern void memory_info_dump(void);
extern size_t mallctl_int64(const char* name, size_t* newval);
extern int mallctl_opt(const char* name, int* newval);
extern void dump_c_mem(void);
+extern int dump_mem_lua(lua_State *L);
#endif /* SKYNET_MALLOC_HOOK_H */
From b2d82373639cf2b3902f23078559b9945d19c023 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Thu, 23 Jul 2015 18:23:47 +0800
Subject: [PATCH 12/97] improve unregister protocol error report
---
lualib/skynet.lua | 20 ++++++++++++++++----
lualib/skynet/debug.lua | 4 ++++
2 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/lualib/skynet.lua b/lualib/skynet.lua
index 02a966fb..cbc16034 100644
--- a/lualib/skynet.lua
+++ b/lualib/skynet.lua
@@ -415,9 +415,13 @@ function skynet.wakeup(co)
end
function skynet.dispatch(typename, func)
- local p = assert(proto[typename],tostring(typename))
- assert(p.dispatch == nil, tostring(typename))
- p.dispatch = func
+ local p = proto[typename]
+ if func then
+ assert(p and (p.dispatch == nil), tostring(typename))
+ p.dispatch = func
+ else
+ return p and p.dispatch
+ end
end
local function unknown_request(session, address, msg, sz, prototype)
@@ -466,7 +470,15 @@ local function raw_dispatch_message(prototype, msg, sz, session, source, ...)
suspend(co, coroutine.resume(co, true, msg, sz))
end
else
- local p = assert(proto[prototype], prototype)
+ local p = proto[prototype]
+ if p == nil then
+ if session ~= 0 then
+ c.send(source, skynet.PTYPE_ERROR, session, "")
+ else
+ unknown_request(session, source, msg, sz, prototype)
+ end
+ return
+ end
local f = p.dispatch
if f then
local ref = watching_service[source]
diff --git a/lualib/skynet/debug.lua b/lualib/skynet/debug.lua
index 0bcb8edb..6c040c24 100644
--- a/lualib/skynet/debug.lua
+++ b/lualib/skynet/debug.lua
@@ -63,6 +63,10 @@ function dbgcmd.REMOTEDEBUG(...)
remotedebug.start(export, ...)
end
+function dbgcmd.SUPPORT(pname)
+ return skynet.ret(skynet.pack(skynet.dispatch(pname) ~= nil))
+end
+
local function _debug_dispatch(session, address, cmd, ...)
local f = dbgcmd[cmd]
assert(f, cmd)
From 1da8a6b38d31b493b64834a52ea3705f6ac3dd0d Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Thu, 23 Jul 2015 18:35:29 +0800
Subject: [PATCH 13/97] lazy init debug command
---
lualib/skynet/debug.lua | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/lualib/skynet/debug.lua b/lualib/skynet/debug.lua
index 6c040c24..635bdb31 100644
--- a/lualib/skynet/debug.lua
+++ b/lualib/skynet/debug.lua
@@ -10,7 +10,10 @@ function skynet.info_func(func)
internal_info_func = func
end
-local dbgcmd = {}
+local dbgcmd
+
+local function init_dbgcmd()
+dbgcmd = {}
function dbgcmd.MEM()
local kb, bytes = collectgarbage "count"
@@ -67,8 +70,11 @@ function dbgcmd.SUPPORT(pname)
return skynet.ret(skynet.pack(skynet.dispatch(pname) ~= nil))
end
+return dbgcmd
+end -- function init_dbgcmd
+
local function _debug_dispatch(session, address, cmd, ...)
- local f = dbgcmd[cmd]
+ local f = (dbgcmd or init_dbgcmd())[cmd] -- lazy init dbgcmd
assert(f, cmd)
f(...)
end
From 0ee61de22ceb4c32a76ab26c67daef94e685d094 Mon Sep 17 00:00:00 2001
From: jintiao
Date: Fri, 24 Jul 2015 00:48:24 +0800
Subject: [PATCH 14/97] skip jemalloc clean if jemalloc's makefile was missing
---
Makefile | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Makefile b/Makefile
index 2982e62c..b92a1a33 100644
--- a/Makefile
+++ b/Makefile
@@ -130,7 +130,9 @@ clean :
rm -f $(SKYNET_BUILD_PATH)/skynet $(CSERVICE_PATH)/*.so $(LUA_CLIB_PATH)/*.so
cleanall: clean
+ifneq (,$(wildcard 3rd/jemalloc/Makefile))
cd 3rd/jemalloc && $(MAKE) clean
+endif
cd 3rd/lua && $(MAKE) clean
rm -f $(LUA_STATICLIB)
From e87ac18b84339a0baa3432b9b352530dca00eb14 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Fri, 24 Jul 2015 17:50:42 +0800
Subject: [PATCH 15/97] expand lua stack first
---
lualib-src/lua-sharedata.c | 1 +
service-src/service_snlua.c | 21 ++++++++++++++++++++-
skynet-src/malloc_hook.c | 1 +
3 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/lualib-src/lua-sharedata.c b/lualib-src/lua-sharedata.c
index 6ef10f0a..e7a27c57 100644
--- a/lualib-src/lua-sharedata.c
+++ b/lualib-src/lua-sharedata.c
@@ -376,6 +376,7 @@ pconv(lua_State *L) {
static void
convert_stringmap(struct context *ctx, struct table *tbl) {
lua_State *L = ctx->L;
+ lua_checkstack(L, ctx->string_index + LUA_MINSTACK);
lua_settop(L, ctx->string_index + 1);
lua_pushvalue(L, 1);
struct state * s = lua_newuserdata(L, sizeof(*s));
diff --git a/service-src/service_snlua.c b/service-src/service_snlua.c
index 89e607f6..b839b117 100644
--- a/service-src/service_snlua.c
+++ b/service-src/service_snlua.c
@@ -12,6 +12,7 @@
struct snlua {
lua_State * L;
struct skynet_context * ctx;
+ FILE *f;
};
// LUA_CACHELIB may defined in patched lua for shared proto
@@ -143,17 +144,35 @@ snlua_init(struct snlua *l, struct skynet_context *ctx, const char * args) {
return 0;
}
+static void *
+lalloc(void *ud, void *ptr, size_t osize, size_t nsize) {
+ struct snlua * l = ud;
+ if (l->f) {
+ fprintf(l->f, "%p %d %d\n", ptr, (int)osize, (int)nsize);
+ }
+ if (nsize == 0) {
+ skynet_free(ptr);
+ return NULL;
+ } else {
+ return skynet_realloc(ptr, nsize);
+ }
+}
+
struct snlua *
snlua_create(void) {
struct snlua * l = skynet_malloc(sizeof(*l));
memset(l,0,sizeof(*l));
- l->L = lua_newstate(skynet_lalloc, NULL);
+ char tmp[L_tmpnam];
+ l->f = fopen(tmpnam(tmp),"wb");
+// printf("%s\n", tmp);
+ l->L = lua_newstate(lalloc, l);
return l;
}
void
snlua_release(struct snlua *l) {
lua_close(l->L);
+ fclose(l->f);
skynet_free(l);
}
diff --git a/skynet-src/malloc_hook.c b/skynet-src/malloc_hook.c
index d9ad6f32..3cff09fa 100644
--- a/skynet-src/malloc_hook.c
+++ b/skynet-src/malloc_hook.c
@@ -218,6 +218,7 @@ skynet_strdup(const char *str) {
void *
skynet_lalloc(void *ud, void *ptr, size_t osize, size_t nsize) {
+ printf("%p osize = %d nsize = %d\n", ptr, (int)osize, (int)nsize);
if (nsize == 0) {
skynet_free(ptr);
return NULL;
From b3f966bcaa00f5e8f3003fc24df7cb705122e356 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Wed, 29 Jul 2015 16:10:38 +0800
Subject: [PATCH 16/97] bugfix: multicast chan gc
---
lualib/multicast.lua | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/lualib/multicast.lua b/lualib/multicast.lua
index 1f5fbd15..181979cb 100644
--- a/lualib/multicast.lua
+++ b/lualib/multicast.lua
@@ -8,7 +8,9 @@ local dispatch = setmetatable({} , {__mode = "kv" })
local chan = {}
local chan_meta = {
__index = chan,
- __gc = unsubscribe,
+ __gc = function(self)
+ self:unsubscribe()
+ end,
__tostring = function (self)
return string.format("[Multicast:%x]",self.channel)
end,
From 4cbead28d5ec78db8fd881a21d89291e65b0d813 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Wed, 29 Jul 2015 16:12:49 +0800
Subject: [PATCH 17/97] skynet.dispatch can replace old func
---
lualib/skynet.lua | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lualib/skynet.lua b/lualib/skynet.lua
index cbc16034..8906f60d 100644
--- a/lualib/skynet.lua
+++ b/lualib/skynet.lua
@@ -417,8 +417,9 @@ end
function skynet.dispatch(typename, func)
local p = proto[typename]
if func then
- assert(p and (p.dispatch == nil), tostring(typename))
+ local ret = p.dispatch
p.dispatch = func
+ return ret
else
return p and p.dispatch
end
From 3b48beb42808f82264081dc5b577f87e08cc42be Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Thu, 30 Jul 2015 15:41:17 +0800
Subject: [PATCH 18/97] bson bugfix
---
lualib-src/lua-bson.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/lualib-src/lua-bson.c b/lualib-src/lua-bson.c
index 52baa64c..9071f56d 100644
--- a/lualib-src/lua-bson.c
+++ b/lualib-src/lua-bson.c
@@ -243,12 +243,16 @@ append_key(struct bson *bs, int type, const char *key, size_t sz) {
write_string(bs, key, sz);
}
+static inline int
+is_32bit(int64_t v) {
+ return v >= INT32_MIN && v <= INT32_MAX;
+}
+
static void
append_number(struct bson *bs, lua_State *L, const char *key, size_t sz) {
if (lua_isinteger(L, -1)) {
int64_t i = lua_tointeger(L, -1);
- int si = i >> 31;
- if (si == 0 || si == -1) {
+ if (is_32bit(i)) {
append_key(bs, BSON_INT32, key, sz);
write_int32(bs, i);
} else {
From 704b016f2cec9ba7d0799c8bd1408b613fef0e64 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Tue, 4 Aug 2015 17:51:35 +0800
Subject: [PATCH 19/97] bugfix: inc session before get channel
---
service/clusterd.lua | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/service/clusterd.lua b/service/clusterd.lua
index b0ee6335..fc8b4126 100644
--- a/service/clusterd.lua
+++ b/service/clusterd.lua
@@ -65,9 +65,11 @@ local function send_request(source, node, addr, msg, sz)
local session = node_session[node] or 1
-- msg is a local pointer, cluster.packrequest will free it
local request, new_session = cluster.packrequest(addr, session, msg, sz)
- local c = node_channel[node]
node_session[node] = new_session
+ -- node_channel[node] may yield or throw error
+ local c = node_channel[node]
+
return c:request(request, session)
end
From b5244b96aa119c2f99f3647dc7c9c63abe84e551 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Tue, 4 Aug 2015 16:47:55 +0800
Subject: [PATCH 20/97] cluster rpc support large package
---
examples/cluster1.lua | 1 +
examples/cluster2.lua | 7 +-
lualib-src/lua-cluster.c | 361 ++++++++++++++++++++++++++++++++++-----
lualib/socketchannel.lua | 68 ++++++--
service/clusterd.lua | 48 +++++-
5 files changed, 418 insertions(+), 67 deletions(-)
diff --git a/examples/cluster1.lua b/examples/cluster1.lua
index 9ba8fcbf..d44899ba 100644
--- a/examples/cluster1.lua
+++ b/examples/cluster1.lua
@@ -6,6 +6,7 @@ local snax = require "snax"
skynet.start(function()
local sdb = skynet.newservice("simpledb")
skynet.name(".simpledb", sdb)
+
print(skynet.call(".simpledb", "lua", "SET", "a", "foobar"))
print(skynet.call(".simpledb", "lua", "SET", "b", "foobar2"))
print(skynet.call(".simpledb", "lua", "GET", "a"))
diff --git a/examples/cluster2.lua b/examples/cluster2.lua
index 09e53076..0aef412c 100644
--- a/examples/cluster2.lua
+++ b/examples/cluster2.lua
@@ -3,7 +3,12 @@ local cluster = require "cluster"
skynet.start(function()
local proxy = cluster.proxy("db", ".simpledb")
- print(skynet.call(proxy, "lua", "GET", "a"))
+ local largekey = string.rep("X", 128*1024)
+ local largevalue = string.rep("R", 100 * 1024)
+ print(skynet.call(proxy, "lua", "SET", largekey, largevalue))
+ local v = skynet.call(proxy, "lua", "GET", largekey)
+ assert(largevalue == v)
+
print(cluster.call("db", ".simpledb", "GET", "a"))
print(cluster.call("db2", ".simpledb", "GET", "b"))
diff --git a/lualib-src/lua-cluster.c b/lualib-src/lua-cluster.c
index e9d9e142..c558fb0f 100644
--- a/lualib-src/lua-cluster.c
+++ b/lualib-src/lua-cluster.c
@@ -15,7 +15,8 @@
uint32_t next_session
*/
-#define TEMP_LENGTH 0x10007
+#define TEMP_LENGTH 0x8200
+#define MULTI_PART 0x8000
static void
fill_uint32(uint8_t * buf, uint32_t n) {
@@ -35,21 +36,69 @@ fill_header(lua_State *L, uint8_t *buf, int sz, void *msg) {
buf[1] = sz & 0xff;
}
-static void
-packreq_number(lua_State *L, int session, void * msg, size_t sz) {
+/*
+ The request package :
+ size <= 0x8000 (32K) and address is id
+ WORD sz+9
+ BYTE 0
+ DWORD addr
+ DWORD session
+ PADDING msg(sz)
+ size > 0x8000 and address is id
+ DWORD 13
+ BYTE 1 ; multireq
+ DWORD addr
+ DWORD session
+ DWORD sz
+
+ size <= 0x8000 (32K) and address is string
+ WORD sz+6+namelen
+ BYTE 0x80
+ BYTE namelen
+ STRING name
+ DWORD session
+ PADDING msg(sz)
+ size > 0x8000 and address is string
+ DWORD 10 + namelen
+ BYTE 0x81
+ BYTE namelen
+ STRING name
+ DWORD session
+ DWORD sz
+
+ multi req
+ WORD sz + 5
+ BYTE 2/3 ; 2:multipart, 3:multipart end
+ DWORD SESSION
+ PADDING msgpart(sz)
+ */
+static int
+packreq_number(lua_State *L, int session, void * msg, uint32_t sz) {
uint32_t addr = (uint32_t)lua_tointeger(L,1);
uint8_t buf[TEMP_LENGTH];
- fill_header(L, buf, sz+9, msg);
- buf[2] = 0;
- fill_uint32(buf+3, addr);
- fill_uint32(buf+7, (uint32_t)session);
- memcpy(buf+11,msg,sz);
+ if (sz < MULTI_PART) {
+ fill_header(L, buf, sz+9, msg);
+ buf[2] = 0;
+ fill_uint32(buf+3, addr);
+ fill_uint32(buf+7, (uint32_t)session);
+ memcpy(buf+11,msg,sz);
- lua_pushlstring(L, (const char *)buf, sz+11);
+ lua_pushlstring(L, (const char *)buf, sz+11);
+ return 0;
+ } else {
+ int part = (sz - 1) / MULTI_PART + 1;
+ fill_header(L, buf, 13, msg);
+ buf[2] = 0x80;
+ fill_uint32(buf+3, addr);
+ fill_uint32(buf+7, (uint32_t)session);
+ fill_uint32(buf+11, sz);
+ lua_pushlstring(L, (const char *)buf, 15);
+ return part;
+ }
}
-static void
-packreq_string(lua_State *L, int session, void * msg, size_t sz) {
+static int
+packreq_string(lua_State *L, int session, void * msg, uint32_t sz) {
size_t namelen = 0;
const char *name = lua_tolstring(L, 1, &namelen);
if (name == NULL || namelen < 1 || namelen > 255) {
@@ -58,13 +107,53 @@ packreq_string(lua_State *L, int session, void * msg, size_t sz) {
}
uint8_t buf[TEMP_LENGTH];
- fill_header(L, buf, sz+5+namelen, msg);
- buf[2] = (uint8_t)namelen;
- memcpy(buf+3, name, namelen);
- fill_uint32(buf+3+namelen, (uint32_t)session);
- memcpy(buf+7+namelen,msg,sz);
+ if (sz < MULTI_PART) {
+ fill_header(L, buf, sz+6+namelen, msg);
+ buf[2] = 0x80;
+ buf[3] = (uint8_t)namelen;
+ memcpy(buf+4, name, namelen);
+ fill_uint32(buf+4+namelen, (uint32_t)session);
+ memcpy(buf+8+namelen,msg,sz);
- lua_pushlstring(L, (const char *)buf, sz+7+namelen);
+ lua_pushlstring(L, (const char *)buf, sz+8+namelen);
+ return 0;
+ } else {
+ int part = (sz - 1) / MULTI_PART + 1;
+ fill_header(L, buf, 10+namelen, msg);
+ buf[2] = 0x81;
+ buf[3] = (uint8_t)namelen;
+ memcpy(buf+4, name, namelen);
+ fill_uint32(buf+4+namelen, (uint32_t)session);
+ fill_uint32(buf+8+namelen, sz);
+
+ lua_pushlstring(L, (const char *)buf, 12+namelen);
+ return part;
+ }
+}
+
+static void
+packreq_multi(lua_State *L, int session, void * msg, uint32_t sz) {
+ uint8_t buf[TEMP_LENGTH];
+ int part = (sz - 1) / MULTI_PART + 1;
+ int i;
+ char *ptr = msg;
+ for (i=0;i MULTI_PART) {
+ s = MULTI_PART;
+ buf[2] = 2;
+ } else {
+ s = sz;
+ buf[2] = 3; // the last multi part
+ }
+ fill_header(L, buf, s+5, msg);
+ fill_uint32(buf+3, (uint32_t)session);
+ memcpy(buf+7, ptr, s);
+ lua_pushlstring(L, (const char *)buf, s+7);
+ lua_rawseti(L, -2, i+1);
+ sz -= s;
+ ptr += s;
+ }
}
static int
@@ -73,24 +162,33 @@ lpackrequest(lua_State *L) {
if (msg == NULL) {
return luaL_error(L, "Invalid request message");
}
- size_t sz = (size_t)luaL_checkinteger(L,4);
+ uint32_t sz = (uint32_t)luaL_checkinteger(L,4);
int session = luaL_checkinteger(L,2);
if (session <= 0) {
skynet_free(msg);
return luaL_error(L, "Invalid request session %d", session);
}
int addr_type = lua_type(L,1);
+ int multipak;
if (addr_type == LUA_TNUMBER) {
- packreq_number(L, session, msg, sz);
+ multipak = packreq_number(L, session, msg, sz);
} else {
- packreq_string(L, session, msg, sz);
+ multipak = packreq_string(L, session, msg, sz);
}
+ int current_session = session;
if (++session < 0) {
session = 1;
}
- skynet_free(msg);
lua_pushinteger(L, session);
- return 2;
+ if (multipak) {
+ lua_createtable(L, multipak, 0);
+ packreq_multi(L, current_session, msg, sz);
+ skynet_free(msg);
+ return 3;
+ } else {
+ skynet_free(msg);
+ return 2;
+ }
}
/*
@@ -99,6 +197,7 @@ lpackrequest(lua_State *L) {
uint32_t or string addr
int session
string msg
+ boolean padding
*/
static inline uint32_t
@@ -107,44 +206,122 @@ unpack_uint32(const uint8_t * buf) {
}
static int
-unpackreq_number(lua_State *L, const uint8_t * buf, size_t sz) {
+unpackreq_number(lua_State *L, const uint8_t * buf, int sz) {
if (sz < 9) {
- return luaL_error(L, "Invalid cluster message");
+ return luaL_error(L, "Invalid cluster message (size=%d)", sz);
}
uint32_t address = unpack_uint32(buf+1);
uint32_t session = unpack_uint32(buf+5);
- lua_pushinteger(L, (uint32_t)address);
- lua_pushinteger(L, (uint32_t)session);
+ lua_pushinteger(L, address);
+ lua_pushinteger(L, session);
lua_pushlstring(L, (const char *)buf+9, sz-9);
return 3;
}
static int
-unpackreq_string(lua_State *L, const uint8_t * buf, size_t sz) {
- size_t namesz = buf[0];
- if (sz < namesz + 5) {
- return luaL_error(L, "Invalid cluster message");
+unpackmreq_number(lua_State *L, const uint8_t * buf, int sz) {
+ if (sz != 15) {
+ return luaL_error(L, "Invalid cluster message size %d (multi req must be 15)", sz);
}
- lua_pushlstring(L, (const char *)buf+1, namesz);
- uint32_t session = unpack_uint32(buf + namesz + 1);
+ uint32_t address = unpack_uint32(buf+1);
+ uint32_t session = unpack_uint32(buf+5);
+ uint32_t size = unpack_uint32(buf+9);
+ lua_pushinteger(L, address);
+ lua_pushinteger(L, session);
+ lua_pushinteger(L, size);
+ lua_pushboolean(L, 1); // padding multi part
+
+ return 4;
+}
+
+static int
+unpackmreq_part(lua_State *L, const uint8_t * buf, int sz) {
+ if (sz < 5) {
+ return luaL_error(L, "Invalid cluster multi part message");
+ }
+ int padding = (buf[0] == 2);
+ uint32_t session = unpack_uint32(buf+1);
+ lua_pushboolean(L, 0); // no address
+ lua_pushinteger(L, session);
+ lua_pushlstring(L, (const char *)buf+5, sz-5);
+ lua_pushboolean(L, padding);
+
+ return 4;
+}
+
+static int
+unpackreq_string(lua_State *L, const uint8_t * buf, int sz) {
+ if (sz < 2) {
+ return luaL_error(L, "Invalid cluster message (size=%d)", sz);
+ }
+ size_t namesz = buf[1];
+ if (sz < namesz + 6) {
+ return luaL_error(L, "Invalid cluster message (size=%d)", sz);
+ }
+ lua_pushlstring(L, (const char *)buf+2, namesz);
+ uint32_t session = unpack_uint32(buf + namesz + 2);
lua_pushinteger(L, (uint32_t)session);
- lua_pushlstring(L, (const char *)buf+1+namesz+4, sz - namesz - 5);
+ lua_pushlstring(L, (const char *)buf+2+namesz+4, sz - namesz - 6);
return 3;
}
+static int
+unpackmreq_string(lua_State *L, const uint8_t * buf, int sz) {
+ if (sz < 2) {
+ return luaL_error(L, "Invalid cluster message (size=%d)", sz);
+ }
+ size_t namesz = buf[1];
+ if (sz < namesz + 10) {
+ return luaL_error(L, "Invalid cluster message (size=%d)", sz);
+ }
+ lua_pushlstring(L, (const char *)buf+2, namesz);
+ uint32_t session = unpack_uint32(buf + namesz + 2);
+ uint32_t size = unpack_uint32(buf + namesz + 6);
+ lua_pushinteger(L, session);
+ lua_pushinteger(L, size);
+ lua_pushboolean(L, 1); // padding multipart
+
+ return 4;
+}
+
static int
lunpackrequest(lua_State *L) {
- size_t sz;
- const char *msg = luaL_checklstring(L,1,&sz);
- if (msg[0] == 0) {
+ size_t ssz;
+ const char *msg = luaL_checklstring(L,1,&ssz);
+ int sz = (int)ssz;
+ switch (msg[0]) {
+ case 0:
return unpackreq_number(L, (const uint8_t *)msg, sz);
- } else {
+ case 1:
+ return unpackmreq_number(L, (const uint8_t *)msg, sz);
+ case 2:
+ case 3:
+ return unpackmreq_part(L, (const uint8_t *)msg, sz);
+ case '\x80':
return unpackreq_string(L, (const uint8_t *)msg, sz);
+ case '\x81':
+ return unpackmreq_string(L, (const uint8_t *)msg, sz);
+ default:
+ return luaL_error(L, "Invalid req package type %d", msg[0]);
}
}
+/*
+ DWORD session
+ BYTE type
+ 0: error
+ 1: ok
+ 2: multi begin
+ 3: multi part
+ 4: multi end
+ PADDING msg
+ type = 0, error msg
+ type = 1, msg
+ type = 2, DWORD size
+ type = 3/4, msg
+ */
/*
int session
boolean ok
@@ -163,14 +340,54 @@ lpackresponse(lua_State *L) {
if (lua_type(L,3) == LUA_TSTRING) {
msg = (void *)lua_tolstring(L, 3, &sz);
- if (sz > 0x1000) {
- sz = 0x1000;
- }
} else {
msg = lua_touserdata(L,3);
sz = (size_t)luaL_checkinteger(L, 4);
}
+ if (!ok) {
+ if (sz > MULTI_PART) {
+ // truncate the error msg if too long
+ sz = MULTI_PART;
+ }
+ } else {
+ if (sz > MULTI_PART) {
+ // return
+ int part = (sz - 1) / MULTI_PART + 1;
+ lua_createtable(L, part+1, 0);
+ uint8_t buf[TEMP_LENGTH];
+
+ // multi part begin
+ fill_header(L, buf, 9, msg);
+ fill_uint32(buf+2, session);
+ buf[6] = 2;
+ fill_uint32(buf+7, (uint32_t)sz);
+ lua_pushlstring(L, (const char *)buf, 11);
+ lua_rawseti(L, -2, 1);
+
+ char * ptr = msg;
+ int i;
+ for (i=0;i MULTI_PART) {
+ s = MULTI_PART;
+ buf[6] = 3;
+ } else {
+ s = sz;
+ buf[6] = 4;
+ }
+ fill_header(L, buf, s+5, msg);
+ fill_uint32(buf+2, session);
+ memcpy(buf+7,ptr,s);
+ lua_pushlstring(L, (const char *)buf, s+7);
+ lua_rawseti(L, -2, i+2);
+ sz -= s;
+ ptr += s;
+ }
+ return 1;
+ }
+ }
+
uint8_t buf[TEMP_LENGTH];
fill_header(L, buf, sz+5, msg);
fill_uint32(buf+2, session);
@@ -187,6 +404,7 @@ lpackresponse(lua_State *L) {
return integer session
boolean ok
string msg
+ boolean padding
*/
static int
lunpackresponse(lua_State *L) {
@@ -197,10 +415,66 @@ lunpackresponse(lua_State *L) {
}
uint32_t session = unpack_uint32((const uint8_t *)buf);
lua_pushinteger(L, (lua_Integer)session);
- lua_pushboolean(L, buf[4]);
- lua_pushlstring(L, buf+5, sz-5);
+ switch(buf[4]) {
+ case 0: // error
+ lua_pushboolean(L, 0);
+ lua_pushlstring(L, buf+5, sz-5);
+ return 3;
+ case 1: // ok
+ case 4: // multi end
+ lua_pushboolean(L, 1);
+ lua_pushlstring(L, buf+5, sz-5);
+ return 3;
+ case 2: // multi begin
+ if (sz != 9) {
+ return 0;
+ }
+ sz = unpack_uint32((const uint8_t *)buf+5);
+ lua_pushboolean(L, 1);
+ lua_pushinteger(L, sz);
+ lua_pushboolean(L, 1);
+ return 4;
+ case 3: // multi part
+ lua_pushboolean(L, 1);
+ lua_pushlstring(L, buf+5, sz-5);
+ lua_pushboolean(L, 1);
+ return 4;
+ default:
+ return 0;
+ }
+}
- return 3;
+static int
+lconcat(lua_State *L) {
+ if (!lua_istable(L,1))
+ return 0;
+ if (lua_geti(L,1,1) != LUA_TNUMBER)
+ return 0;
+ int sz = lua_tointeger(L,-1);
+ lua_pop(L,1);
+ char * buff = skynet_malloc(sz);
+ int idx = 2;
+ int offset = 0;
+ while(lua_geti(L,1,idx) == LUA_TSTRING) {
+ size_t s;
+ const char * str = lua_tolstring(L, -1, &s);
+ if (s+offset > sz) {
+ skynet_free(buff);
+ return 0;
+ }
+ memcpy(buff+offset, str, s);
+ lua_pop(L,1);
+ offset += s;
+ ++idx;
+ }
+ if (offset != sz) {
+ skynet_free(buff);
+ return 0;
+ }
+ // buff/sz will send to other service, See clusterd.lua
+ lua_pushlightuserdata(L, buff);
+ lua_pushinteger(L, sz);
+ return 2;
}
int
@@ -210,6 +484,7 @@ luaopen_cluster_core(lua_State *L) {
{ "unpackrequest", lunpackrequest },
{ "packresponse", lpackresponse },
{ "unpackresponse", lunpackresponse },
+ { "concat", lconcat },
{ NULL, NULL },
};
luaL_checkversion(L);
diff --git a/lualib/socketchannel.lua b/lualib/socketchannel.lua
index 282e6283..9ff5d451 100644
--- a/lualib/socketchannel.lua
+++ b/lualib/socketchannel.lua
@@ -81,15 +81,27 @@ local function dispatch_by_session(self)
local response = self.__response
-- response() return session
while self.__sock do
- local ok , session, result_ok, result_data = pcall(response, self.__sock)
+ local ok , session, result_ok, result_data, padding = pcall(response, self.__sock)
if ok and session then
local co = self.__thread[session]
- self.__thread[session] = nil
if co then
- self.__result[co] = result_ok
- self.__result_data[co] = result_data
- skynet.wakeup(co)
+ if padding and result_ok then
+ -- If padding is true, append result_data to a table (self.__result_data[co])
+ local result = self.__result_data[co] or {}
+ self.__result_data[co] = result
+ table.insert(result, result_data)
+ else
+ self.__thread[session] = nil
+ 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
+ self.__thread[session] = nil
skynet.error("socket: unknown session :", session)
end
else
@@ -127,11 +139,23 @@ local function dispatch_by_order(self)
wakeup_all(self)
end
else
- local ok, result_ok, result_data = pcall(func, self.__sock)
+ local ok, result_ok, result_data, padding = pcall(func, self.__sock)
if ok then
- self.__result[co] = result_ok
- self.__result_data[co] = result_data
- skynet.wakeup(co)
+ 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
@@ -314,13 +338,27 @@ local function wait_for_response(self, response)
end
end
-function channel:request(request, response)
- assert(block_connect(self, true)) -- connect once
+local socket_write = socket.write
+local socket_lwrite = socket.lwrite
- if not socket.write(self.__sock[1], request) then
- close_channel_socket(self)
- wakeup_all(self)
- error(socket_error)
+function channel:request(request, response, padding)
+ assert(block_connect(self, true)) -- connect once
+ local fd = self.__sock[1]
+
+ if padding then
+ -- padding may be a table, to support multi part request
+ -- multi part request use low priority socket write
+ -- socket_lwrite returns nothing
+ socket_lwrite(fd , request)
+ for _,v in ipairs(padding) do
+ socket_lwrite(fd, v)
+ end
+ else
+ if not socket_write(fd , request) then
+ close_channel_socket(self)
+ wakeup_all(self)
+ error(socket_error)
+ end
end
if response == nil then
diff --git a/service/clusterd.lua b/service/clusterd.lua
index fc8b4126..b3c74722 100644
--- a/service/clusterd.lua
+++ b/service/clusterd.lua
@@ -11,7 +11,7 @@ local command = {}
local function read_response(sock)
local sz = socket.header(sock:read(2))
local msg = sock:read(sz)
- return cluster.unpackresponse(msg) -- session, ok, data
+ return cluster.unpackresponse(msg) -- session, ok, data, padding
end
local function open_channel(t, key)
@@ -64,19 +64,23 @@ end
local function send_request(source, node, addr, msg, sz)
local session = node_session[node] or 1
-- msg is a local pointer, cluster.packrequest will free it
- local request, new_session = cluster.packrequest(addr, session, msg, sz)
+ local request, new_session, padding = cluster.packrequest(addr, session, msg, sz)
node_session[node] = new_session
-- node_channel[node] may yield or throw error
local c = node_channel[node]
- return c:request(request, session)
+ return c:request(request, session, padding)
end
function command.req(...)
local ok, msg, sz = pcall(send_request, ...)
if ok then
- skynet.ret(msg, sz)
+ if type(msg) == "table" then
+ skynet.ret(cluster.concat(msg))
+ else
+ skynet.ret(msg)
+ end
else
skynet.error(msg)
skynet.response()(false)
@@ -93,23 +97,51 @@ function command.proxy(source, node, name)
skynet.ret(skynet.pack(proxy[fullname]))
end
-local request_fd = {}
+local large_request = {}
function command.socket(source, subcmd, fd, msg)
if subcmd == "data" then
- local addr, session, msg = cluster.unpackrequest(msg)
- local ok , msg, sz = pcall(skynet.rawcall, addr, "lua", msg)
+ local sz
+ local addr, session, msg, padding = cluster.unpackrequest(msg)
+ if padding then
+ local req = large_request[session] or { addr = addr }
+ large_request[session] = req
+ table.insert(req, msg)
+ return
+ else
+ local req = large_request[session]
+ if req then
+ large_request[session] = nil
+ table.insert(req, msg)
+ msg,sz = cluster.concat(req)
+ addr = req.addr
+ end
+ if not msg then
+ local response = cluster.packresponse(session, false, "Invalid large req")
+ socket.write(fd, response)
+ return
+ end
+ end
+ local ok , msg, sz = pcall(skynet.rawcall, addr, "lua", msg, sz)
local response
if ok then
response = cluster.packresponse(session, true, msg, sz)
+ if type(response) == "table" then
+ for _, v in ipairs(response) do
+ socket.lwrite(fd, v)
+ end
+ else
+ socket.write(fd, response)
+ end
else
response = cluster.packresponse(session, false, msg)
+ socket.write(fd, response)
end
- socket.write(fd, response)
elseif subcmd == "open" then
skynet.error(string.format("socket accept from %s", msg))
skynet.call(source, "lua", "accept", fd)
else
+ large_request = {}
skynet.error(string.format("socket %s %d : %s", subcmd, fd, msg))
end
end
From aff73cbed7e6cebd796b1f83cac150901dec1172 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Wed, 5 Aug 2015 12:23:35 +0800
Subject: [PATCH 21/97] Increase message size 16M(24bit) limit to 56bit on
64bit arch
---
examples/config.userlog | 5 +----
service-src/service_harbor.c | 9 +++++++--
skynet-src/skynet_error.c | 2 +-
skynet-src/skynet_handle.h | 4 +++-
skynet-src/skynet_harbor.c | 6 ++++--
skynet-src/skynet_harbor.h | 4 ----
skynet-src/skynet_mq.h | 4 ++++
skynet-src/skynet_server.c | 12 ++++++------
skynet-src/skynet_socket.c | 4 ++--
skynet-src/skynet_start.c | 1 +
skynet-src/skynet_timer.c | 4 ++--
11 files changed, 31 insertions(+), 24 deletions(-)
diff --git a/examples/config.userlog b/examples/config.userlog
index 97bef6ef..dcd47b7b 100644
--- a/examples/config.userlog
+++ b/examples/config.userlog
@@ -3,12 +3,9 @@ thread = 8
logger = "userlog"
logservice = "snlua"
logpath = "."
-harbor = 1
-address = "127.0.0.1:2526"
-master = "127.0.0.1:2013"
+harbor = 0
start = "main" -- main script
bootstrap = "snlua bootstrap" -- The service for bootstrap
-standalone = "0.0.0.0:2013"
luaservice = root.."service/?.lua;"..root.."test/?.lua;"..root.."examples/?.lua"
lualoader = "lualib/loader.lua"
-- preload = "./examples/preload.lua" -- run preload.lua before every lua service run
diff --git a/service-src/service_harbor.c b/service-src/service_harbor.c
index 5940d62c..90d8bcc6 100644
--- a/service-src/service_harbor.c
+++ b/service-src/service_harbor.c
@@ -1,6 +1,7 @@
#include "skynet.h"
#include "skynet_harbor.h"
#include "skynet_socket.h"
+#include "skynet_handle.h"
/*
harbor listen the PTYPE_HARBOR (in text)
@@ -323,9 +324,13 @@ forward_local_messsage(struct harbor *h, void *msg, int sz) {
static void
send_remote(struct skynet_context * ctx, int fd, const char * buffer, size_t sz, struct remote_message_header * cookie) {
- uint32_t sz_header = sz+sizeof(*cookie);
+ size_t sz_header = sz+sizeof(*cookie);
+ if (sz_header > UINT32_MAX) {
+ skynet_error(ctx, "remote message from :%08x to :%08x is too large.", cookie->source, cookie->destination);
+ return;
+ }
uint8_t * sendbuf = skynet_malloc(sz_header+4);
- to_bigendian(sendbuf, sz_header);
+ to_bigendian(sendbuf, (uint32_t)sz_header);
memcpy(sendbuf+4, buffer, sz);
header_to_message(cookie, sendbuf+4+sz);
diff --git a/skynet-src/skynet_error.c b/skynet-src/skynet_error.c
index b9c53efd..962ea597 100644
--- a/skynet-src/skynet_error.c
+++ b/skynet-src/skynet_error.c
@@ -54,7 +54,7 @@ skynet_error(struct skynet_context * context, const char *msg, ...) {
}
smsg.session = 0;
smsg.data = data;
- smsg.sz = len | (PTYPE_TEXT << HANDLE_REMOTE_SHIFT);
+ smsg.sz = len | ((size_t)PTYPE_TEXT << MESSAGE_TYPE_SHIFT);
skynet_context_push(logger, &smsg);
}
diff --git a/skynet-src/skynet_handle.h b/skynet-src/skynet_handle.h
index e067eed0..293b6571 100644
--- a/skynet-src/skynet_handle.h
+++ b/skynet-src/skynet_handle.h
@@ -3,7 +3,9 @@
#include
-#include "skynet_harbor.h"
+// reserve high 8 bits for remote id
+#define HANDLE_MASK 0xffffff
+#define HANDLE_REMOTE_SHIFT 24
struct skynet_context;
diff --git a/skynet-src/skynet_harbor.c b/skynet-src/skynet_harbor.c
index 379fce80..5e39ca62 100644
--- a/skynet-src/skynet_harbor.c
+++ b/skynet-src/skynet_harbor.c
@@ -1,6 +1,8 @@
#include "skynet.h"
#include "skynet_harbor.h"
#include "skynet_server.h"
+#include "skynet_mq.h"
+#include "skynet_handle.h"
#include
#include
@@ -11,8 +13,8 @@ static unsigned int HARBOR = ~0;
void
skynet_harbor_send(struct remote_message *rmsg, uint32_t source, int session) {
- int type = rmsg->sz >> HANDLE_REMOTE_SHIFT;
- rmsg->sz &= HANDLE_MASK;
+ int type = rmsg->sz >> MESSAGE_TYPE_SHIFT;
+ rmsg->sz &= MESSAGE_TYPE_MASK;
assert(type != PTYPE_SYSTEM && type != PTYPE_HARBOR && REMOTE);
skynet_context_send(REMOTE, rmsg, sizeof(*rmsg) , source, type , session);
}
diff --git a/skynet-src/skynet_harbor.h b/skynet-src/skynet_harbor.h
index 62982455..97a76c20 100644
--- a/skynet-src/skynet_harbor.h
+++ b/skynet-src/skynet_harbor.h
@@ -7,10 +7,6 @@
#define GLOBALNAME_LENGTH 16
#define REMOTE_MAX 256
-// reserve high 8 bits for remote id
-#define HANDLE_MASK 0xffffff
-#define HANDLE_REMOTE_SHIFT 24
-
struct remote_name {
char name[GLOBALNAME_LENGTH];
uint32_t handle;
diff --git a/skynet-src/skynet_mq.h b/skynet-src/skynet_mq.h
index 17178b4f..3721e32b 100644
--- a/skynet-src/skynet_mq.h
+++ b/skynet-src/skynet_mq.h
@@ -11,6 +11,10 @@ struct skynet_message {
size_t sz;
};
+// type is encoding in skynet_message.sz high 8bit
+#define MESSAGE_TYPE_MASK (SIZE_MAX >> 8)
+#define MESSAGE_TYPE_SHIFT ((sizeof(size_t)-1) * 8)
+
struct message_queue;
void skynet_globalmq_push(struct message_queue * queue);
diff --git a/skynet-src/skynet_server.c b/skynet-src/skynet_server.c
index ea1aadcf..52331193 100644
--- a/skynet-src/skynet_server.c
+++ b/skynet-src/skynet_server.c
@@ -246,8 +246,8 @@ dispatch_message(struct skynet_context *ctx, struct skynet_message *msg) {
assert(ctx->init);
CHECKCALLING_BEGIN(ctx)
pthread_setspecific(G_NODE.handle_key, (void *)(uintptr_t)(ctx->handle));
- int type = msg->sz >> HANDLE_REMOTE_SHIFT;
- size_t sz = msg->sz & HANDLE_MASK;
+ int type = msg->sz >> MESSAGE_TYPE_SHIFT;
+ size_t sz = msg->sz & MESSAGE_TYPE_MASK;
if (ctx->logfile) {
skynet_log_output(ctx->logfile, msg->source, type, msg->session, msg->data, sz);
}
@@ -662,13 +662,13 @@ _filter_args(struct skynet_context * context, int type, int *session, void ** da
*data = msg;
}
- *sz |= type << HANDLE_REMOTE_SHIFT;
+ *sz |= (size_t)type << MESSAGE_TYPE_SHIFT;
}
int
skynet_send(struct skynet_context * context, uint32_t source, uint32_t destination , int type, int session, void * data, size_t sz) {
- if ((sz & HANDLE_MASK) != sz) {
- skynet_error(context, "The message to %x is too large (sz = %lu)", destination, sz);
+ if ((sz & MESSAGE_TYPE_MASK) != sz) {
+ skynet_error(context, "The message to %x is too large", destination);
skynet_free(data);
return -1;
}
@@ -751,7 +751,7 @@ skynet_context_send(struct skynet_context * ctx, void * msg, size_t sz, uint32_t
smsg.source = source;
smsg.session = session;
smsg.data = msg;
- smsg.sz = sz | type << HANDLE_REMOTE_SHIFT;
+ smsg.sz = sz | (size_t)type << MESSAGE_TYPE_SHIFT;
skynet_mq_push(ctx->queue, &smsg);
}
diff --git a/skynet-src/skynet_socket.c b/skynet-src/skynet_socket.c
index 3f2c9a04..2ea26c0a 100644
--- a/skynet-src/skynet_socket.c
+++ b/skynet-src/skynet_socket.c
@@ -33,7 +33,7 @@ skynet_socket_free() {
static void
forward_message(int type, bool padding, struct socket_message * result) {
struct skynet_socket_message *sm;
- int sz = sizeof(*sm);
+ size_t sz = sizeof(*sm);
if (padding) {
if (result->data) {
sz += strlen(result->data);
@@ -56,7 +56,7 @@ forward_message(int type, bool padding, struct socket_message * result) {
message.source = 0;
message.session = 0;
message.data = sm;
- message.sz = sz | PTYPE_SOCKET << HANDLE_REMOTE_SHIFT;
+ message.sz = sz | ((size_t)PTYPE_SOCKET << MESSAGE_TYPE_SHIFT);
if (skynet_context_push((uint32_t)result->opaque, &message)) {
// todo: report somewhere to close socket
diff --git a/skynet-src/skynet_start.c b/skynet-src/skynet_start.c
index 4123c624..5345c76c 100644
--- a/skynet-src/skynet_start.c
+++ b/skynet-src/skynet_start.c
@@ -8,6 +8,7 @@
#include "skynet_monitor.h"
#include "skynet_socket.h"
#include "skynet_daemon.h"
+#include "skynet_harbor.h"
#include
#include
diff --git a/skynet-src/skynet_timer.c b/skynet-src/skynet_timer.c
index f7d5a1ff..a6b4bb87 100644
--- a/skynet-src/skynet_timer.c
+++ b/skynet-src/skynet_timer.c
@@ -146,7 +146,7 @@ dispatch_list(struct timer_node *current) {
message.source = 0;
message.session = event->session;
message.data = NULL;
- message.sz = PTYPE_RESPONSE << HANDLE_REMOTE_SHIFT;
+ message.sz = (size_t)MESSAGE_TYPE_SHIFT << MESSAGE_TYPE_SHIFT;
skynet_context_push(event->handle, &message);
@@ -214,7 +214,7 @@ skynet_timeout(uint32_t handle, int time, int session) {
message.source = 0;
message.session = session;
message.data = NULL;
- message.sz = PTYPE_RESPONSE << HANDLE_REMOTE_SHIFT;
+ message.sz = (size_t)PTYPE_RESPONSE << MESSAGE_TYPE_SHIFT;
if (skynet_context_push(handle, &message)) {
return -1;
From b4048a8eab2ff01888a931ec7e24541d45c7a2ba Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Wed, 5 Aug 2015 16:42:05 +0800
Subject: [PATCH 22/97] bugfix: typo
---
skynet-src/skynet_timer.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/skynet-src/skynet_timer.c b/skynet-src/skynet_timer.c
index a6b4bb87..f23114dc 100644
--- a/skynet-src/skynet_timer.c
+++ b/skynet-src/skynet_timer.c
@@ -146,7 +146,7 @@ dispatch_list(struct timer_node *current) {
message.source = 0;
message.session = event->session;
message.data = NULL;
- message.sz = (size_t)MESSAGE_TYPE_SHIFT << MESSAGE_TYPE_SHIFT;
+ message.sz = (size_t)PTYPE_RESPONSE << MESSAGE_TYPE_SHIFT;
skynet_context_push(event->handle, &message);
From 3156661e0b1fb85dd7e70f7df8c532ba0367e3e3 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Thu, 6 Aug 2015 20:00:48 +0800
Subject: [PATCH 23/97] bugfix: response function for socket channel
---
lualib/mysql.lua | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lualib/mysql.lua b/lualib/mysql.lua
index a83a0986..305e900b 100755
--- a/lualib/mysql.lua
+++ b/lualib/mysql.lua
@@ -386,7 +386,8 @@ end
local function _recv_decode_packet_resp(self)
return function(sock)
- return true, _recv_packet(self,sock)
+ -- don't return more than 2 results
+ return true, (_recv_packet(self,sock))
end
end
From e9cfdba22a43e4ef9caf29b4f711ab27231426a0 Mon Sep 17 00:00:00 2001
From: snail
Date: Fri, 7 Aug 2015 10:38:57 +0800
Subject: [PATCH 24/97] 'hotfix' code cannot use '_ENV'
If there's no global variable or function used in any interface of a snax service,the upvalue "_ENV" for 'hotfix' is not set. This modify is not complete, it depend's on the 'collect_uv' method having upvalue '_ENV',maybe other good method to get upvalue index of '_ENV'.
---
lualib/snax/hotfix.lua | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/lualib/snax/hotfix.lua b/lualib/snax/hotfix.lua
index 1a60383a..3a6e4e3e 100644
--- a/lualib/snax/hotfix.lua
+++ b/lualib/snax/hotfix.lua
@@ -49,7 +49,9 @@ local function collect_all_uv(funcs)
collect_uv(v[4], global, envid(v[4]))
end
end
-
+ if not global["_ENV"] then
+ global["_ENV"] = {func = collect_uv, index = 1}
+ end
return global
end
From 5936d3616ccfb0ec49005a19a4c38a758889f6b9 Mon Sep 17 00:00:00 2001
From: BITMAN
Date: Fri, 7 Aug 2015 13:51:10 +0800
Subject: [PATCH 25/97] Packing multipart req number first byte is 1
---
lualib-src/lua-cluster.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lualib-src/lua-cluster.c b/lualib-src/lua-cluster.c
index c558fb0f..40cc453e 100644
--- a/lualib-src/lua-cluster.c
+++ b/lualib-src/lua-cluster.c
@@ -88,7 +88,7 @@ packreq_number(lua_State *L, int session, void * msg, uint32_t sz) {
} else {
int part = (sz - 1) / MULTI_PART + 1;
fill_header(L, buf, 13, msg);
- buf[2] = 0x80;
+ buf[2] = 1;
fill_uint32(buf+3, addr);
fill_uint32(buf+7, (uint32_t)session);
fill_uint32(buf+11, sz);
From c16ae57639b9568156e7cdb14c27d385d13d838f Mon Sep 17 00:00:00 2001
From: felixdae
Date: Fri, 7 Aug 2015 18:36:30 +0800
Subject: [PATCH 26/97] not work with telnet due to \r\n
---
service/debug_console.lua | 1 +
1 file changed, 1 insertion(+)
diff --git a/service/debug_console.lua b/service/debug_console.lua
index 139e76bb..97b35806 100644
--- a/service/debug_console.lua
+++ b/service/debug_console.lua
@@ -228,6 +228,7 @@ function COMMAND.debug(address, fd)
skynet.fork(function()
repeat
local cmdline = socket.readline(fd, "\n")
+ cmdline = cmdline:gsub("(.*)\r$", "%1")
if not cmdline then
skynet.send(agent, "lua", "cmd", "cont")
break
From 2935ba3521eed5a8f612bf9bd90538a4e1ec63a9 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Mon, 10 Aug 2015 16:17:55 +0800
Subject: [PATCH 27/97] Release alpha9
---
HISTORY.md | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/HISTORY.md b/HISTORY.md
index 8f0a1ac4..a970b7c2 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -1,3 +1,12 @@
+v1.0.0-alpha9 (2015-8-10)
+-----------
+* Improve lua serialization , support pairs metamethod.
+* Bugfix : sproto (See commits log of sproto)
+* Add user log service support (In config)
+* Remove the size limit of cluster RPC message.
+* Remove the size limit of local message.
+* Other minor bugfix (See commits log)
+
v1.0.0-alpha8 (2015-6-29)
-----------
* Update lua 5.3.1
From 6fa436e8ff980c05239c8aaa5015d424d0065bdc Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Mon, 10 Aug 2015 22:06:36 +0800
Subject: [PATCH 28/97] add core.intcommand , See Issue #321
---
lualib-src/lua-skynet.c | 23 +++++++++++++++++++++++
lualib/skynet.lua | 12 +++++-------
2 files changed, 28 insertions(+), 7 deletions(-)
diff --git a/lualib-src/lua-skynet.c b/lualib-src/lua-skynet.c
index f1594f79..c92ff98d 100644
--- a/lualib-src/lua-skynet.c
+++ b/lualib-src/lua-skynet.c
@@ -118,6 +118,28 @@ _command(lua_State *L) {
return 0;
}
+static int
+_intcommand(lua_State *L) {
+ struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1));
+ const char * cmd = luaL_checkstring(L,1);
+ const char * result;
+ const char * parm = NULL;
+ char tmp[64]; // for integer parm
+ if (lua_gettop(L) == 2) {
+ int32_t n = (int32_t)luaL_checkinteger(L,2);
+ sprintf(tmp, "%d", n);
+ parm = tmp;
+ }
+
+ result = skynet_command(context, cmd, parm);
+ if (result) {
+ lua_Integer r = strtoll(result, NULL, 0);
+ lua_pushinteger(L, r);
+ return 1;
+ }
+ return 0;
+}
+
static int
_genid(lua_State *L) {
struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1));
@@ -310,6 +332,7 @@ luaopen_skynet_core(lua_State *L) {
{ "genid", _genid },
{ "redirect", _redirect },
{ "command" , _command },
+ { "intcommand", _intcommand },
{ "error", _error },
{ "tostring", _tostring },
{ "harbor", _harbor },
diff --git a/lualib/skynet.lua b/lualib/skynet.lua
index 8906f60d..31efffcb 100644
--- a/lualib/skynet.lua
+++ b/lualib/skynet.lua
@@ -248,18 +248,16 @@ function suspend(co, result, command, param, size)
end
function skynet.timeout(ti, func)
- local session = c.command("TIMEOUT",tostring(ti))
+ local session = c.intcommand("TIMEOUT",ti)
assert(session)
- session = tonumber(session)
local co = co_create(func)
assert(session_id_coroutine[session] == nil)
session_id_coroutine[session] = co
end
function skynet.sleep(ti)
- local session = c.command("TIMEOUT",tostring(ti))
+ local session = c.intcommand("TIMEOUT",ti)
assert(session)
- session = tonumber(session)
local succ, ret = coroutine_yield("SLEEP", session)
sleep_session[coroutine.running()] = nil
if succ then
@@ -301,11 +299,11 @@ function skynet.localname(name)
end
function skynet.now()
- return tonumber(c.command("NOW"))
+ return c.intcommand("NOW")
end
function skynet.starttime()
- return tonumber(c.command("STARTTIME"))
+ return c.intcommand("STARTTIME")
end
function skynet.time()
@@ -643,7 +641,7 @@ function skynet.endless()
end
function skynet.mqlen()
- return tonumber(c.command "MQLEN")
+ return c.intcommand "MQLEN"
end
function skynet.task(ret)
From 947727e33acb7d26e500875cb17537946e481697 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Tue, 11 Aug 2015 13:21:24 +0800
Subject: [PATCH 29/97] add new socket message WARNING
---
examples/watchdog.lua | 5 +++++
lualib-src/lua-netpack.c | 9 ++++++++-
lualib/skynet.lua | 2 +-
lualib/snax/gateserver.lua | 6 ++++++
lualib/socket.lua | 25 +++++++++++++++++++++++++
service-src/service_gate.c | 3 +++
service-src/service_harbor.c | 7 +++++++
service/gate.lua | 4 ++++
skynet-src/skynet_socket.c | 11 +++++++----
skynet-src/skynet_socket.h | 1 +
10 files changed, 67 insertions(+), 6 deletions(-)
diff --git a/examples/watchdog.lua b/examples/watchdog.lua
index 29111033..efee5e24 100644
--- a/examples/watchdog.lua
+++ b/examples/watchdog.lua
@@ -32,6 +32,11 @@ function SOCKET.error(fd, msg)
close_agent(fd)
end
+function SOCKET.warning(fd, size)
+ -- size K bytes havn't send out in fd
+ print("socket warning", fd, size)
+end
+
function SOCKET.data(fd, msg)
end
diff --git a/lualib-src/lua-netpack.c b/lualib-src/lua-netpack.c
index 1839abe3..88a54d3d 100644
--- a/lualib-src/lua-netpack.c
+++ b/lualib-src/lua-netpack.c
@@ -19,6 +19,7 @@
#define TYPE_ERROR 3
#define TYPE_OPEN 4
#define TYPE_CLOSE 5
+#define TYPE_WARNING 6
/*
Each package is uint16 + data , uint16 (serialized in big-endian) is the number of bytes comprising the data .
@@ -371,6 +372,11 @@ lfilter(lua_State *L) {
lua_pushinteger(L, message->id);
pushstring(L, buffer, size);
return 4;
+ case SKYNET_SOCKET_TYPE_WARNING:
+ lua_pushvalue(L, lua_upvalueindex(TYPE_WARNING));
+ lua_pushinteger(L, message->id);
+ lua_pushinteger(L, message->ud);
+ return 4;
default:
// never get here
return 1;
@@ -537,8 +543,9 @@ luaopen_netpack(lua_State *L) {
lua_pushliteral(L, "error");
lua_pushliteral(L, "open");
lua_pushliteral(L, "close");
+ lua_pushliteral(L, "warning");
- lua_pushcclosure(L, lfilter, 5);
+ lua_pushcclosure(L, lfilter, 6);
lua_setfield(L, -2, "filter");
return 1;
diff --git a/lualib/skynet.lua b/lualib/skynet.lua
index 31efffcb..e4f46908 100644
--- a/lualib/skynet.lua
+++ b/lualib/skynet.lua
@@ -271,7 +271,7 @@ function skynet.sleep(ti)
end
function skynet.yield()
- return skynet.sleep("0")
+ return skynet.sleep(0)
end
function skynet.wait()
diff --git a/lualib/snax/gateserver.lua b/lualib/snax/gateserver.lua
index e68efc12..dfce2fa9 100644
--- a/lualib/snax/gateserver.lua
+++ b/lualib/snax/gateserver.lua
@@ -114,6 +114,12 @@ function gateserver.start(handler)
close_fd(fd)
end
+ function MSG.warning(fd, size)
+ if handler.warning then
+ handler.warning(fd, size)
+ end
+ end
+
skynet.register_protocol {
name = "socket",
id = skynet.PTYPE_SOCKET, -- PTYPE_SOCKET = 6
diff --git a/lualib/socket.lua b/lualib/socket.lua
index 8d98e5a3..c5fe7858 100644
--- a/lualib/socket.lua
+++ b/lualib/socket.lua
@@ -133,6 +133,25 @@ socket_message[6] = function(id, size, data, address)
s.callback(str, address)
end
+local function default_warning(id, size)
+ local s = socket_pool[id]
+ local last = s.warningsize or 0
+ if last + 64 < size then -- if size increase 64K
+ s.warningsize = size
+ skynet.error(string.format("WARNING: %d K bytes need to send out (fd = %d)", size, id))
+ end
+ s.warningsize = size
+end
+
+-- SKYNET_SOCKET_TYPE_WARNING
+socket_message[7] = function(id, size)
+ local s = socket_pool[id]
+ if s then
+ local warning = s.warning or default_warning
+ warning(id, size)
+ end
+end
+
skynet.register_protocol {
name = "socket",
id = skynet.PTYPE_SOCKET, -- PTYPE_SOCKET = 6
@@ -404,4 +423,10 @@ end
socket.sendto = assert(driver.udp_send)
socket.udp_address = assert(driver.udp_address)
+function socket.warning(id, callback)
+ local obj = socket_pool[id]
+ assert(obj)
+ obj.warning = callback
+end
+
return socket
diff --git a/service-src/service_gate.c b/service-src/service_gate.c
index 9f5d98ec..ec44c722 100644
--- a/service-src/service_gate.c
+++ b/service-src/service_gate.c
@@ -262,6 +262,9 @@ dispatch_socket_message(struct gate *g, const struct skynet_socket_message * mes
skynet_socket_start(ctx, message->ud);
}
break;
+ case SKYNET_SOCKET_TYPE_WARNING:
+ skynet_error(ctx, "fd (%d) send buffer (%d)K", message->id, message->ud);
+ break;
}
}
diff --git a/service-src/service_harbor.c b/service-src/service_harbor.c
index 90d8bcc6..5ff618f1 100644
--- a/service-src/service_harbor.c
+++ b/service-src/service_harbor.c
@@ -662,6 +662,13 @@ mainloop(struct skynet_context * context, void * ud, int type, int session, uint
case SKYNET_SOCKET_TYPE_CONNECT:
// fd forward to this service
break;
+ case SKYNET_SOCKET_TYPE_WARNING: {
+ int id = harbor_id(h, message->id);
+ if (id) {
+ skynet_error(context, "message havn't send to Harbor (%d) reach %d K", id, message->ud);
+ }
+ break;
+ }
default:
skynet_error(context, "recv invalid socket message type %d", type);
break;
diff --git a/service/gate.lua b/service/gate.lua
index 9fe3a491..78fb099f 100644
--- a/service/gate.lua
+++ b/service/gate.lua
@@ -63,6 +63,10 @@ function handler.error(fd, msg)
skynet.send(watchdog, "lua", "socket", "error", fd, msg)
end
+function handler.warning(fd, size)
+ skynet.send(watchdog, "lua", "socket", "warning", fd, size)
+end
+
local CMD = {}
function CMD.forward(source, fd, client, address)
diff --git a/skynet-src/skynet_socket.c b/skynet-src/skynet_socket.c
index 2ea26c0a..9301419f 100644
--- a/skynet-src/skynet_socket.c
+++ b/skynet-src/skynet_socket.c
@@ -109,10 +109,13 @@ check_wsz(struct skynet_context *ctx, int id, void *buffer, int64_t wsz) {
if (wsz < 0) {
return -1;
} else if (wsz > 1024 * 1024) {
- int kb4 = wsz / 1024 / 4;
- if (kb4 % 256 == 0) {
- skynet_error(ctx, "%d Mb bytes on socket %d need to send out", (int)(wsz / (1024 * 1024)), id);
- }
+ struct skynet_socket_message tmp;
+ tmp.type = SKYNET_SOCKET_TYPE_WARNING;
+ tmp.id = id;
+ tmp.ud = (int)(wsz / 1024);
+ tmp.buffer = NULL;
+ skynet_send(ctx, 0, skynet_context_handle(ctx), PTYPE_SOCKET, 0 , &tmp, sizeof(tmp));
+// skynet_error(ctx, "%d Mb bytes on socket %d need to send out", (int)(wsz / (1024 * 1024)), id);
}
return 0;
}
diff --git a/skynet-src/skynet_socket.h b/skynet-src/skynet_socket.h
index 5327f09f..bcdc137c 100644
--- a/skynet-src/skynet_socket.h
+++ b/skynet-src/skynet_socket.h
@@ -9,6 +9,7 @@ struct skynet_context;
#define SKYNET_SOCKET_TYPE_ACCEPT 4
#define SKYNET_SOCKET_TYPE_ERROR 5
#define SKYNET_SOCKET_TYPE_UDP 6
+#define SKYNET_SOCKET_TYPE_WARNING 7
struct skynet_socket_message {
int type;
From d3771edc9d5a878c34de954cc845d7096a4bcc1d Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Tue, 11 Aug 2015 14:04:15 +0800
Subject: [PATCH 30/97] The cluster message never great than 64K now
---
lualib-src/lua-cluster.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/lualib-src/lua-cluster.c b/lualib-src/lua-cluster.c
index 40cc453e..4afe0e6d 100644
--- a/lualib-src/lua-cluster.c
+++ b/lualib-src/lua-cluster.c
@@ -1,6 +1,7 @@
#include
#include
#include
+#include
#include "skynet.h"
@@ -28,10 +29,7 @@ fill_uint32(uint8_t * buf, uint32_t n) {
static void
fill_header(lua_State *L, uint8_t *buf, int sz, void *msg) {
- if (sz >= 0x10000) {
- skynet_free(msg);
- luaL_error(L, "request message is too long %d", sz);
- }
+ assert(sz < 0x10000);
buf[0] = (sz >> 8) & 0xff;
buf[1] = sz & 0xff;
}
From 926b44ddf6b8e6a71dfe340e4af5bcac21d8a09d Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Tue, 11 Aug 2015 14:09:16 +0800
Subject: [PATCH 31/97] remove unused parm
---
lualib-src/lua-cluster.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/lualib-src/lua-cluster.c b/lualib-src/lua-cluster.c
index 4afe0e6d..e35615c7 100644
--- a/lualib-src/lua-cluster.c
+++ b/lualib-src/lua-cluster.c
@@ -28,7 +28,7 @@ fill_uint32(uint8_t * buf, uint32_t n) {
}
static void
-fill_header(lua_State *L, uint8_t *buf, int sz, void *msg) {
+fill_header(lua_State *L, uint8_t *buf, int sz) {
assert(sz < 0x10000);
buf[0] = (sz >> 8) & 0xff;
buf[1] = sz & 0xff;
@@ -75,7 +75,7 @@ packreq_number(lua_State *L, int session, void * msg, uint32_t sz) {
uint32_t addr = (uint32_t)lua_tointeger(L,1);
uint8_t buf[TEMP_LENGTH];
if (sz < MULTI_PART) {
- fill_header(L, buf, sz+9, msg);
+ fill_header(L, buf, sz+9);
buf[2] = 0;
fill_uint32(buf+3, addr);
fill_uint32(buf+7, (uint32_t)session);
@@ -85,7 +85,7 @@ packreq_number(lua_State *L, int session, void * msg, uint32_t sz) {
return 0;
} else {
int part = (sz - 1) / MULTI_PART + 1;
- fill_header(L, buf, 13, msg);
+ fill_header(L, buf, 13);
buf[2] = 1;
fill_uint32(buf+3, addr);
fill_uint32(buf+7, (uint32_t)session);
@@ -106,7 +106,7 @@ packreq_string(lua_State *L, int session, void * msg, uint32_t sz) {
uint8_t buf[TEMP_LENGTH];
if (sz < MULTI_PART) {
- fill_header(L, buf, sz+6+namelen, msg);
+ fill_header(L, buf, sz+6+namelen);
buf[2] = 0x80;
buf[3] = (uint8_t)namelen;
memcpy(buf+4, name, namelen);
@@ -117,7 +117,7 @@ packreq_string(lua_State *L, int session, void * msg, uint32_t sz) {
return 0;
} else {
int part = (sz - 1) / MULTI_PART + 1;
- fill_header(L, buf, 10+namelen, msg);
+ fill_header(L, buf, 10+namelen);
buf[2] = 0x81;
buf[3] = (uint8_t)namelen;
memcpy(buf+4, name, namelen);
@@ -144,7 +144,7 @@ packreq_multi(lua_State *L, int session, void * msg, uint32_t sz) {
s = sz;
buf[2] = 3; // the last multi part
}
- fill_header(L, buf, s+5, msg);
+ fill_header(L, buf, s+5);
fill_uint32(buf+3, (uint32_t)session);
memcpy(buf+7, ptr, s);
lua_pushlstring(L, (const char *)buf, s+7);
@@ -356,7 +356,7 @@ lpackresponse(lua_State *L) {
uint8_t buf[TEMP_LENGTH];
// multi part begin
- fill_header(L, buf, 9, msg);
+ fill_header(L, buf, 9);
fill_uint32(buf+2, session);
buf[6] = 2;
fill_uint32(buf+7, (uint32_t)sz);
@@ -374,7 +374,7 @@ lpackresponse(lua_State *L) {
s = sz;
buf[6] = 4;
}
- fill_header(L, buf, s+5, msg);
+ fill_header(L, buf, s+5);
fill_uint32(buf+2, session);
memcpy(buf+7,ptr,s);
lua_pushlstring(L, (const char *)buf, s+7);
@@ -387,7 +387,7 @@ lpackresponse(lua_State *L) {
}
uint8_t buf[TEMP_LENGTH];
- fill_header(L, buf, sz+5, msg);
+ fill_header(L, buf, sz+5);
fill_uint32(buf+2, session);
buf[6] = ok;
memcpy(buf+7,msg,sz);
From 7547126570000ddce915c58e7590430be55d67c4 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Wed, 12 Aug 2015 12:03:52 +0800
Subject: [PATCH 32/97] bugfix: memory leak , See Issue #323
---
3rd/lua/lfunc.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/3rd/lua/lfunc.c b/3rd/lua/lfunc.c
index ae603c8f..b0d9db4b 100644
--- a/3rd/lua/lfunc.c
+++ b/3rd/lua/lfunc.c
@@ -135,6 +135,7 @@ static void freesharedproto (lua_State *L, SharedProto *f) {
luaM_freearray(L, f->lineinfo, f->sizelineinfo);
luaM_freearray(L, f->locvars, f->sizelocvars);
luaM_freearray(L, f->upvalues, f->sizeupvalues);
+ luaM_free(L, f);
}
void luaF_freeproto (lua_State *L, Proto *f) {
From a4f827a48d1d83fd29acc7135267b7d7e6688dc6 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Wed, 12 Aug 2015 14:53:36 +0800
Subject: [PATCH 33/97] use string for msgserver request
---
lualib-src/lua-netpack.c | 15 ++-------------
lualib/snax/msgserver.lua | 16 ++++++++--------
2 files changed, 10 insertions(+), 21 deletions(-)
diff --git a/lualib-src/lua-netpack.c b/lualib-src/lua-netpack.c
index 88a54d3d..0ec6f7e9 100644
--- a/lualib-src/lua-netpack.c
+++ b/lualib-src/lua-netpack.c
@@ -506,19 +506,8 @@ ltostring(lua_State *L) {
if (ptr == NULL) {
lua_pushliteral(L, "");
} else {
- if (lua_isnumber(L, 3)) {
- int offset = lua_tointeger(L, 3);
- if (offset < 0) {
- return luaL_error(L, "Invalid offset %d", offset);
- }
- if (offset > size) {
- offset = size;
- }
- lua_pushlstring(L, (const char *)ptr + offset, size-offset);
- } else {
- lua_pushlstring(L, (const char *)ptr, size);
- skynet_free(ptr);
- }
+ lua_pushlstring(L, (const char *)ptr, size);
+ skynet_free(ptr);
}
return 1;
}
diff --git a/lualib/snax/msgserver.lua b/lualib/snax/msgserver.lua
index a70ea415..c480a8a6 100644
--- a/lualib/snax/msgserver.lua
+++ b/lualib/snax/msgserver.lua
@@ -70,7 +70,7 @@ Config for server.start:
conf.login_handler(uid, secret) -> subid : the function when a new user login, alloc a subid for it. (may call by login server)
conf.logout_handler(uid, subid) : the functon when a user logout. (may call by agent)
conf.kick_handler(uid, subid) : the functon when a user logout. (may call by login server)
- conf.request_handler(username, session, msg, sz) : the function when recv a new request.
+ conf.request_handler(username, session, msg) : the function when recv a new request.
conf.register_handler(servername) : call when gate open
conf.disconnect_handler(username) : call when a connection disconnect (afk)
]]
@@ -234,10 +234,10 @@ function server.start(conf)
end
end
- local function do_request(fd, msg, sz)
+ local function do_request(fd, message)
local u = assert(connection[fd], "invalid fd")
- local msg_sz = sz - 4
- local session = netpack.tostring(msg, sz, msg_sz)
+ local session = string.unpack("I4", message, -4)
+ message = message:sub(1,-5)
local p = u.response[session]
if p then
-- session can be reuse in the same connection
@@ -256,7 +256,7 @@ function server.start(conf)
if p == nil then
p = { fd }
u.response[session] = p
- local ok, result = pcall(conf.request_handler, u.username, msg, msg_sz)
+ local ok, result = pcall(conf.request_handler, u.username, message)
result = result or ""
-- NOTICE: YIELD here, socket may close.
if not ok then
@@ -270,7 +270,6 @@ function server.start(conf)
p[3] = u.version
p[4] = u.index
else
- netpack.tostring(msg, sz) -- request before, so free msg
-- update version/index, change return fd.
-- resend response.
p[1] = fd
@@ -292,10 +291,11 @@ function server.start(conf)
end
local function request(fd, msg, sz)
- local ok, err = pcall(do_request, fd, msg, sz)
+ local message = netpack.tostring(msg, sz)
+ local ok, err = pcall(do_request, fd, message)
-- not atomic, may yield
if not ok then
- skynet.error(string.format("Invalid package %s : %s", err, netpack.tostring(msg, sz)))
+ skynet.error(string.format("Invalid package %s : %s", err, message))
if connection[fd] then
gateserver.closeclient(fd)
end
From adc39705f392b0a7cc6cadd62b9bf6ed703699f3 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Wed, 12 Aug 2015 20:56:29 +0800
Subject: [PATCH 34/97] remove unused netpack c api
---
lualib-src/lua-netpack.c | 53 ---------------------------------------
lualib/snax/msgserver.lua | 10 ++++----
2 files changed, 5 insertions(+), 58 deletions(-)
diff --git a/lualib-src/lua-netpack.c b/lualib-src/lua-netpack.c
index 0ec6f7e9..193938b1 100644
--- a/lualib-src/lua-netpack.c
+++ b/lualib-src/lua-netpack.c
@@ -448,57 +448,6 @@ lpack(lua_State *L) {
return 2;
}
-static int
-lpack_string(lua_State *L) {
- uint8_t tmp[SMALLSTRING+2];
- size_t len;
- uint8_t *buffer;
- const char * ptr = tolstring(L, &len, 1);
- if (len > 0x10000) {
- return luaL_error(L, "Invalid size (too long) of data : %d", (int)len);
- }
-
- if (len <= SMALLSTRING) {
- buffer = tmp;
- } else {
- buffer = lua_newuserdata(L, len + 2);
- }
-
- write_size(buffer, len);
- memcpy(buffer+2, ptr, len);
- lua_pushlstring(L, (const char *)buffer, len+2);
-
- return 1;
-}
-
-static int
-lpack_padding(lua_State *L) {
- uint8_t tmp[SMALLSTRING+2];
- size_t content_sz;
- uint8_t *buffer;
- const char * ptr = tolstring(L, &content_sz, 2);
- size_t cookie_sz = 0;
- const char * cookie = luaL_checklstring(L,1,&cookie_sz);
- size_t len = cookie_sz + content_sz;
-
- if (len > 0x10000) {
- return luaL_error(L, "Invalid size (too long) of data : %d", (int)len);
- }
-
- if (len <= SMALLSTRING) {
- buffer = tmp;
- } else {
- buffer = lua_newuserdata(L, len + 2);
- }
-
- write_size(buffer, len);
- memcpy(buffer+2, ptr, content_sz);
- memcpy(buffer+2+content_sz, cookie, cookie_sz);
- lua_pushlstring(L, (const char *)buffer, len+2);
-
- return 1;
-}
-
static int
ltostring(lua_State *L) {
void * ptr = lua_touserdata(L, 1);
@@ -518,8 +467,6 @@ luaopen_netpack(lua_State *L) {
luaL_Reg l[] = {
{ "pop", lpop },
{ "pack", lpack },
- { "pack_string", lpack_string },
- { "pack_padding", lpack_padding },
{ "clear", lclear },
{ "tostring", ltostring },
{ NULL, NULL },
diff --git a/lualib/snax/msgserver.lua b/lualib/snax/msgserver.lua
index c480a8a6..765387cc 100644
--- a/lualib/snax/msgserver.lua
+++ b/lualib/snax/msgserver.lua
@@ -236,7 +236,7 @@ function server.start(conf)
local function do_request(fd, message)
local u = assert(connection[fd], "invalid fd")
- local session = string.unpack("I4", message, -4)
+ local session = string.unpack(">I4", message, -4)
message = message:sub(1,-5)
local p = u.response[session]
if p then
@@ -257,16 +257,16 @@ function server.start(conf)
p = { fd }
u.response[session] = p
local ok, result = pcall(conf.request_handler, u.username, message)
- result = result or ""
-- NOTICE: YIELD here, socket may close.
+ result = result or ""
if not ok then
skynet.error(result)
- result = "\0" .. session
+ result = string.pack(">BI4", 0, session)
else
- result = result .. '\1' .. session
+ result = result .. string.pack(">BI4", 1, session)
end
- p[2] = netpack.pack_string(result)
+ p[2] = string.pack(">s2",result)
p[3] = u.version
p[4] = u.index
else
From 0ce9921c251988ed50519d3d43d7143efa5b4bc2 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Wed, 12 Aug 2015 21:16:02 +0800
Subject: [PATCH 35/97] remove unused sz
---
examples/login/gated.lua | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/examples/login/gated.lua b/examples/login/gated.lua
index 4a024699..0b8c53b7 100644
--- a/examples/login/gated.lua
+++ b/examples/login/gated.lua
@@ -74,9 +74,9 @@ function server.disconnect_handler(username)
end
-- call by self (when recv a request from client)
-function server.request_handler(username, msg, sz)
+function server.request_handler(username, msg)
local u = username_map[username]
- return skynet.tostring(skynet.rawcall(u.agent, "client", msg, sz))
+ return skynet.tostring(skynet.rawcall(u.agent, "client", msg))
end
-- call by self (when gate open)
From bf8f9b8654fe5764b5249766b9f7611adb6e8dd0 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Thu, 13 Aug 2015 21:00:20 +0800
Subject: [PATCH 36/97] add pthread lock
---
Makefile | 9 ++--
lualib-src/lua-bson.c | 3 +-
lualib-src/lua-clientsocket.c | 16 ++++----
lualib-src/lua-debugchannel.c | 26 ++++++------
lualib-src/lua-multicast.c | 4 +-
lualib-src/lua-sharedata.c | 9 ++--
lualib-src/lua-stm.c | 9 ++--
skynet-src/atomic.h | 14 +++++++
skynet-src/malloc_hook.c | 17 ++++----
skynet-src/rwlock.h | 40 ++++++++++++++++++
skynet-src/skynet_env.c | 16 ++++----
skynet-src/skynet_module.c | 15 ++++---
skynet-src/skynet_monitor.c | 3 +-
skynet-src/skynet_mq.c | 42 +++++++++----------
skynet-src/skynet_server.c | 25 +++++++-----
skynet-src/skynet_timer.c | 21 +++++-----
skynet-src/socket_server.c | 7 ++--
skynet-src/spinlock.h | 77 +++++++++++++++++++++++++++++++++++
18 files changed, 249 insertions(+), 104 deletions(-)
create mode 100644 skynet-src/atomic.h
create mode 100644 skynet-src/spinlock.h
diff --git a/Makefile b/Makefile
index b92a1a33..98f7d1c9 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,8 @@ CSERVICE_PATH ?= cservice
SKYNET_BUILD_PATH ?= .
-CFLAGS = -g -O2 -Wall -I$(LUA_INC) $(MYCFLAGS)
+CFLAGS = -g -O2 -Wall -I$(LUA_INC) $(MYCFLAGS)
+# CFLAGS += -DUSE_PTHREAD_LOCK
# lua
@@ -79,7 +80,7 @@ $(LUA_CLIB_PATH)/socketdriver.so : lualib-src/lua-socket.c | $(LUA_CLIB_PATH)
$(CC) $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src -Iservice-src
$(LUA_CLIB_PATH)/bson.so : lualib-src/lua-bson.c | $(LUA_CLIB_PATH)
- $(CC) $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src
+ $(CC) $(CFLAGS) $(SHARED) -Iskynet-src $^ -o $@ -Iskynet-src
$(LUA_CLIB_PATH)/mongo.so : lualib-src/lua-mongo.c | $(LUA_CLIB_PATH)
$(CC) $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src
@@ -109,7 +110,7 @@ $(LUA_CLIB_PATH)/crypt.so : lualib-src/lua-crypt.c lualib-src/lsha1.c | $(LUA_CL
$(CC) $(CFLAGS) $(SHARED) $^ -o $@
$(LUA_CLIB_PATH)/sharedata.so : lualib-src/lua-sharedata.c | $(LUA_CLIB_PATH)
- $(CC) $(CFLAGS) $(SHARED) $^ -o $@
+ $(CC) $(CFLAGS) $(SHARED) -Iskynet-src $^ -o $@
$(LUA_CLIB_PATH)/stm.so : lualib-src/lua-stm.c | $(LUA_CLIB_PATH)
$(CC) $(CFLAGS) $(SHARED) -Iskynet-src $^ -o $@
@@ -124,7 +125,7 @@ $(LUA_CLIB_PATH)/mysqlaux.so : lualib-src/lua-mysqlaux.c | $(LUA_CLIB_PATH)
$(CC) $(CFLAGS) $(SHARED) $^ -o $@
$(LUA_CLIB_PATH)/debugchannel.so : lualib-src/lua-debugchannel.c | $(LUA_CLIB_PATH)
- $(CC) $(CFLAGS) $(SHARED) $^ -o $@
+ $(CC) $(CFLAGS) $(SHARED) -Iskynet-src $^ -o $@
clean :
rm -f $(SKYNET_BUILD_PATH)/skynet $(CSERVICE_PATH)/*.so $(LUA_CLIB_PATH)/*.so
diff --git a/lualib-src/lua-bson.c b/lualib-src/lua-bson.c
index 9071f56d..0fc26985 100644
--- a/lualib-src/lua-bson.c
+++ b/lualib-src/lua-bson.c
@@ -8,6 +8,7 @@
#include
#include
#include
+#include "atomic.h"
#define DEFAULT_CAP 64
#define MAX_NUMBER 1024
@@ -1140,7 +1141,7 @@ lobjectid(lua_State *L) {
} else {
time_t ti = time(NULL);
// old_counter is a static var, use atom inc.
- uint32_t id = __sync_fetch_and_add(&oid_counter,1);
+ uint32_t id = ATOM_FINC(&oid_counter);
oid[2] = (ti>>24) & 0xff;
oid[3] = (ti>>16) & 0xff;
diff --git a/lualib-src/lua-clientsocket.c b/lualib-src/lua-clientsocket.c
index 89bfe1f8..fa1a88e8 100644
--- a/lualib-src/lua-clientsocket.c
+++ b/lualib-src/lua-clientsocket.c
@@ -128,11 +128,8 @@ lusleep(lua_State *L) {
#define QUEUE_SIZE 1024
-#define LOCK(q) while (__sync_lock_test_and_set(&(q)->lock,1)) {}
-#define UNLOCK(q) __sync_lock_release(&(q)->lock);
-
struct queue {
- int lock;
+ pthread_mutex_t lock;
int head;
int tail;
char * queue[QUEUE_SIZE];
@@ -153,7 +150,7 @@ readline_stdin(void * arg) {
memcpy(str, tmp, n);
str[n] = 0;
- LOCK(q);
+ pthread_mutex_lock(&q->lock);
q->queue[q->tail] = str;
if (++q->tail >= QUEUE_SIZE) {
@@ -163,7 +160,7 @@ readline_stdin(void * arg) {
// queue overflow
exit(1);
}
- UNLOCK(q);
+ pthread_mutex_unlock(&q->lock);
}
return NULL;
}
@@ -171,16 +168,16 @@ readline_stdin(void * arg) {
static int
lreadstdin(lua_State *L) {
struct queue *q = lua_touserdata(L, lua_upvalueindex(1));
- LOCK(q);
+ pthread_mutex_lock(&q->lock);
if (q->head == q->tail) {
- UNLOCK(q);
+ pthread_mutex_unlock(&q->lock);
return 0;
}
char * str = q->queue[q->head];
if (++q->head >= QUEUE_SIZE) {
q->head = 0;
}
- UNLOCK(q);
+ pthread_mutex_unlock(&q->lock);
lua_pushstring(L, str);
free(str);
return 1;
@@ -201,6 +198,7 @@ luaopen_clientsocket(lua_State *L) {
struct queue * q = lua_newuserdata(L, sizeof(*q));
memset(q, 0, sizeof(*q));
+ pthread_mutex_init(&q->lock, NULL);
lua_pushcclosure(L, lreadstdin, 1);
lua_setfield(L, -2, "readstdin");
diff --git a/lualib-src/lua-debugchannel.c b/lualib-src/lua-debugchannel.c
index 9e4539d3..ad7e1f1b 100644
--- a/lualib-src/lua-debugchannel.c
+++ b/lualib-src/lua-debugchannel.c
@@ -4,10 +4,9 @@
#include
#include
#include
+#include "spinlock.h"
#define METANAME "debugchannel"
-#define LOCK(q) while (__sync_lock_test_and_set(&(q)->lock,1)) {}
-#define UNLOCK(q) __sync_lock_release(&(q)->lock);
struct command {
struct command * next;
@@ -15,7 +14,7 @@ struct command {
};
struct channel {
- int lock;
+ struct spinlock lock;
int ref;
struct command * head;
struct command * tail;
@@ -26,6 +25,7 @@ channel_new() {
struct channel * c = malloc(sizeof(*c));
memset(c, 0 , sizeof(*c));
c->ref = 1;
+ SPIN_INIT(c)
return c;
}
@@ -33,21 +33,21 @@ channel_new() {
static struct channel *
channel_connect(struct channel *c) {
struct channel * ret = NULL;
- LOCK(c)
+ SPIN_LOCK(c)
if (c->ref == 1) {
++c->ref;
ret = c;
}
- UNLOCK(c)
+ SPIN_UNLOCK(c)
return ret;
}
static struct channel *
channel_release(struct channel *c) {
- LOCK(c)
+ SPIN_LOCK(c)
--c->ref;
if (c->ref > 0) {
- UNLOCK(c)
+ SPIN_UNLOCK(c)
return c;
}
// never unlock while reference is 0
@@ -59,6 +59,8 @@ channel_release(struct channel *c) {
free(p);
p = next;
}
+ SPIN_UNLOCK(c)
+ SPIN_DESTROY(c)
free(c);
return NULL;
}
@@ -67,9 +69,9 @@ channel_release(struct channel *c) {
static struct command *
channel_read(struct channel *c, double timeout) {
struct command * ret = NULL;
- LOCK(c)
+ SPIN_LOCK(c)
if (c->head == NULL) {
- UNLOCK(c)
+ SPIN_UNLOCK(c)
int ti = (int)(timeout * 100000);
usleep(ti);
return NULL;
@@ -79,7 +81,7 @@ channel_read(struct channel *c, double timeout) {
if (c->head == NULL) {
c->tail = NULL;
}
- UNLOCK(c)
+ SPIN_UNLOCK(c)
return ret;
}
@@ -90,14 +92,14 @@ channel_write(struct channel *c, const char * s, size_t sz) {
cmd->sz = sz;
cmd->next = NULL;
memcpy(cmd+1, s, sz);
- LOCK(c)
+ SPIN_LOCK(c)
if (c->tail == NULL) {
c->head = c->tail = cmd;
} else {
c->tail->next = cmd;
c->tail = cmd;
}
- UNLOCK(c)
+ SPIN_UNLOCK(c)
}
struct channel_box {
diff --git a/lualib-src/lua-multicast.c b/lualib-src/lua-multicast.c
index 599616f9..cff8d434 100644
--- a/lualib-src/lua-multicast.c
+++ b/lualib-src/lua-multicast.c
@@ -5,6 +5,8 @@
#include
#include
+#include "atomic.h"
+
struct mc_package {
int reference;
uint32_t size;
@@ -116,7 +118,7 @@ static int
mc_closelocal(lua_State *L) {
struct mc_package *pack = lua_touserdata(L,1);
- int ref = __sync_sub_and_fetch(&pack->reference, 1);
+ int ref = ATOM_DEC(&pack->reference);
if (ref <= 0) {
skynet_free(pack->data);
skynet_free(pack);
diff --git a/lualib-src/lua-sharedata.c b/lualib-src/lua-sharedata.c
index e7a27c57..99cadd15 100644
--- a/lualib-src/lua-sharedata.c
+++ b/lualib-src/lua-sharedata.c
@@ -4,6 +4,7 @@
#include
#include
#include
+#include "atomic.h"
#define KEYTYPE_INTEGER 0
#define KEYTYPE_STRING 1
@@ -663,7 +664,7 @@ releaseobj(lua_State *L) {
struct ctrl *c = lua_touserdata(L, 1);
struct table *tbl = c->root;
struct state *s = lua_touserdata(tbl->L, 1);
- __sync_fetch_and_sub(&s->ref, 1);
+ ATOM_DEC(&s->ref);
c->root = NULL;
c->update = NULL;
@@ -674,7 +675,7 @@ static int
lboxconf(lua_State *L) {
struct table * tbl = get_table(L,1);
struct state * s = lua_touserdata(tbl->L, 1);
- __sync_fetch_and_add(&s->ref, 1);
+ ATOM_INC(&s->ref);
struct ctrl * c = lua_newuserdata(L, sizeof(*c));
c->root = tbl;
@@ -719,7 +720,7 @@ static int
lincref(lua_State *L) {
struct table *tbl = get_table(L,1);
struct state * s = lua_touserdata(tbl->L, 1);
- int ref = __sync_add_and_fetch(&s->ref, 1);
+ int ref = ATOM_INC(&s->ref);
lua_pushinteger(L , ref);
return 1;
@@ -729,7 +730,7 @@ static int
ldecref(lua_State *L) {
struct table *tbl = get_table(L,1);
struct state * s = lua_touserdata(tbl->L, 1);
- int ref = __sync_sub_and_fetch(&s->ref, 1);
+ int ref = ATOM_DEC(&s->ref);
lua_pushinteger(L , ref);
return 1;
diff --git a/lualib-src/lua-stm.c b/lualib-src/lua-stm.c
index b38fbcd1..e175d100 100644
--- a/lualib-src/lua-stm.c
+++ b/lualib-src/lua-stm.c
@@ -7,6 +7,7 @@
#include "rwlock.h"
#include "skynet_malloc.h"
+#include "atomic.h"
struct stm_object {
struct rwlock lock;
@@ -45,7 +46,7 @@ static void
stm_releasecopy(struct stm_copy *copy) {
if (copy == NULL)
return;
- if (__sync_sub_and_fetch(©->reference, 1) == 0) {
+ if (ATOM_DEC(©->reference) == 0) {
skynet_free(copy->msg);
skynet_free(copy);
}
@@ -70,7 +71,7 @@ stm_release(struct stm_object *obj) {
static void
stm_releasereader(struct stm_object *obj) {
rwlock_rlock(&obj->lock);
- if (__sync_sub_and_fetch(&obj->reference,1) == 0) {
+ if (ATOM_DEC(&obj->reference) == 0) {
// last reader, no writer. so no need to unlock
assert(obj->copy == NULL);
skynet_free(obj);
@@ -82,7 +83,7 @@ stm_releasereader(struct stm_object *obj) {
static void
stm_grab(struct stm_object *obj) {
rwlock_rlock(&obj->lock);
- int ref = __sync_fetch_and_add(&obj->reference,1);
+ int ref = ATOM_FINC(&obj->reference);
rwlock_runlock(&obj->lock);
assert(ref > 0);
}
@@ -92,7 +93,7 @@ stm_copy(struct stm_object *obj) {
rwlock_rlock(&obj->lock);
struct stm_copy * ret = obj->copy;
if (ret) {
- int ref = __sync_fetch_and_add(&ret->reference,1);
+ int ref = ATOM_FINC(&ret->reference);
assert(ref > 0);
}
rwlock_runlock(&obj->lock);
diff --git a/skynet-src/atomic.h b/skynet-src/atomic.h
new file mode 100644
index 00000000..f79c7148
--- /dev/null
+++ b/skynet-src/atomic.h
@@ -0,0 +1,14 @@
+#ifndef SKYNET_ATOMIC_H
+#define SKYNET_ATOMIC_H
+
+#define ATOM_CAS(ptr, oval, nval) __sync_bool_compare_and_swap(ptr, oval, nval)
+#define ATOM_CAS_POINTER(ptr, oval, nval) __sync_bool_compare_and_swap(ptr, oval, nval)
+#define ATOM_INC(ptr) __sync_add_and_fetch(ptr, 1)
+#define ATOM_FINC(ptr) __sync_fetch_and_add(ptr, 1)
+#define ATOM_DEC(ptr) __sync_sub_and_fetch(ptr, 1)
+#define ATOM_FDEC(ptr) __sync_fetch_and_sub(ptr, 1)
+#define ATOM_ADD(ptr,n) __sync_add_and_fetch(ptr, n)
+#define ATOM_SUB(ptr,n) __sync_sub_and_fetch(ptr, n)
+#define ATOM_AND(ptr,n) __sync_and_and_fetch(ptr, n)
+
+#endif
diff --git a/skynet-src/malloc_hook.c b/skynet-src/malloc_hook.c
index d9ad6f32..3b072168 100644
--- a/skynet-src/malloc_hook.c
+++ b/skynet-src/malloc_hook.c
@@ -6,6 +6,7 @@
#include "malloc_hook.h"
#include "skynet.h"
+#include "atomic.h"
static size_t _used_memory = 0;
static size_t _memory_block = 0;
@@ -32,11 +33,11 @@ get_allocated_field(uint32_t handle) {
ssize_t old_alloc = data->allocated;
if(old_handle == 0 || old_alloc <= 0) {
// data->allocated may less than zero, because it may not count at start.
- if(!__sync_bool_compare_and_swap(&data->handle, old_handle, handle)) {
+ if(!ATOM_CAS(&data->handle, old_handle, handle)) {
return 0;
}
if (old_alloc < 0) {
- __sync_bool_compare_and_swap(&data->allocated, old_alloc, 0);
+ ATOM_CAS(&data->allocated, old_alloc, 0);
}
}
if(data->handle != handle) {
@@ -47,21 +48,21 @@ get_allocated_field(uint32_t handle) {
inline static void
update_xmalloc_stat_alloc(uint32_t handle, size_t __n) {
- __sync_add_and_fetch(&_used_memory, __n);
- __sync_add_and_fetch(&_memory_block, 1);
+ ATOM_ADD(&_used_memory, __n);
+ ATOM_INC(&_memory_block);
ssize_t* allocated = get_allocated_field(handle);
if(allocated) {
- __sync_add_and_fetch(allocated, __n);
+ ATOM_ADD(allocated, __n);
}
}
inline static void
update_xmalloc_stat_free(uint32_t handle, size_t __n) {
- __sync_sub_and_fetch(&_used_memory, __n);
- __sync_sub_and_fetch(&_memory_block, 1);
+ ATOM_SUB(&_used_memory, __n);
+ ATOM_DEC(&_memory_block);
ssize_t* allocated = get_allocated_field(handle);
if(allocated) {
- __sync_sub_and_fetch(allocated, __n);
+ ATOM_SUB(allocated, __n);
}
}
diff --git a/skynet-src/rwlock.h b/skynet-src/rwlock.h
index e366f18c..5a995918 100644
--- a/skynet-src/rwlock.h
+++ b/skynet-src/rwlock.h
@@ -1,6 +1,8 @@
#ifndef SKYNET_RWLOCK_H
#define SKYNET_RWLOCK_H
+#ifndef USE_PTHREAD_LOCK
+
struct rwlock {
int write;
int read;
@@ -45,4 +47,42 @@ rwlock_runlock(struct rwlock *lock) {
__sync_sub_and_fetch(&lock->read,1);
}
+#else
+
+#include
+
+// only for some platform doesn't have __sync_*
+// todo: check the result of pthread api
+
+struct rwlock {
+ pthread_rwlock_t lock;
+};
+
+static inline void
+rwlock_init(struct rwlock *lock) {
+ pthread_rwlock_init(&lock->lock, NULL);
+}
+
+static inline void
+rwlock_rlock(struct rwlock *lock) {
+ pthread_rwlock_rdlock(&lock->lock);
+}
+
+static inline void
+rwlock_wlock(struct rwlock *lock) {
+ pthread_rwlock_wrlock(&lock->lock);
+}
+
+static inline void
+rwlock_wunlock(struct rwlock *lock) {
+ pthread_rwlock_unlock(&lock->lock);
+}
+
+static inline void
+rwlock_runlock(struct rwlock *lock) {
+ pthread_rwlock_unlock(&lock->lock);
+}
+
+#endif
+
#endif
diff --git a/skynet-src/skynet_env.c b/skynet-src/skynet_env.c
index 9dbbcf9c..a5882f21 100644
--- a/skynet-src/skynet_env.c
+++ b/skynet-src/skynet_env.c
@@ -1,5 +1,6 @@
#include "skynet.h"
#include "skynet_env.h"
+#include "spinlock.h"
#include
#include
@@ -8,18 +9,15 @@
#include
struct skynet_env {
- int lock;
+ struct spinlock lock;
lua_State *L;
};
static struct skynet_env *E = NULL;
-#define LOCK(q) while (__sync_lock_test_and_set(&(q)->lock,1)) {}
-#define UNLOCK(q) __sync_lock_release(&(q)->lock);
-
const char *
skynet_getenv(const char *key) {
- LOCK(E)
+ SPIN_LOCK(E)
lua_State *L = E->L;
@@ -27,14 +25,14 @@ skynet_getenv(const char *key) {
const char * result = lua_tostring(L, -1);
lua_pop(L, 1);
- UNLOCK(E)
+ SPIN_UNLOCK(E)
return result;
}
void
skynet_setenv(const char *key, const char *value) {
- LOCK(E)
+ SPIN_LOCK(E)
lua_State *L = E->L;
lua_getglobal(L, key);
@@ -43,12 +41,12 @@ skynet_setenv(const char *key, const char *value) {
lua_pushstring(L,value);
lua_setglobal(L,key);
- UNLOCK(E)
+ SPIN_UNLOCK(E)
}
void
skynet_env_init() {
E = skynet_malloc(sizeof(*E));
- E->lock = 0;
+ SPIN_INIT(E)
E->L = luaL_newstate();
}
diff --git a/skynet-src/skynet_module.c b/skynet-src/skynet_module.c
index 2da34629..d586427f 100644
--- a/skynet-src/skynet_module.c
+++ b/skynet-src/skynet_module.c
@@ -1,6 +1,7 @@
#include "skynet.h"
#include "skynet_module.h"
+#include "spinlock.h"
#include
#include
@@ -13,7 +14,7 @@
struct modules {
int count;
- int lock;
+ struct spinlock lock;
const char * path;
struct skynet_module m[MAX_MODULE_TYPE];
};
@@ -95,7 +96,7 @@ skynet_module_query(const char * name) {
if (result)
return result;
- while(__sync_lock_test_and_set(&M->lock,1)) {}
+ SPIN_LOCK(M)
result = _query(name); // double check
@@ -114,21 +115,22 @@ skynet_module_query(const char * name) {
}
}
- __sync_lock_release(&M->lock);
+ SPIN_UNLOCK(M)
return result;
}
void
skynet_module_insert(struct skynet_module *mod) {
- while(__sync_lock_test_and_set(&M->lock,1)) {}
+ SPIN_LOCK(M)
struct skynet_module * m = _query(mod->name);
assert(m == NULL && M->count < MAX_MODULE_TYPE);
int index = M->count;
M->m[index] = *mod;
++M->count;
- __sync_lock_release(&M->lock);
+
+ SPIN_UNLOCK(M)
}
void *
@@ -164,7 +166,8 @@ skynet_module_init(const char *path) {
struct modules *m = skynet_malloc(sizeof(*m));
m->count = 0;
m->path = skynet_strdup(path);
- m->lock = 0;
+
+ SPIN_INIT(m)
M = m;
}
diff --git a/skynet-src/skynet_monitor.c b/skynet-src/skynet_monitor.c
index 9ee302e5..8d47fc89 100644
--- a/skynet-src/skynet_monitor.c
+++ b/skynet-src/skynet_monitor.c
@@ -3,6 +3,7 @@
#include "skynet_monitor.h"
#include "skynet_server.h"
#include "skynet.h"
+#include "atomic.h"
#include
#include
@@ -30,7 +31,7 @@ void
skynet_monitor_trigger(struct skynet_monitor *sm, uint32_t source, uint32_t destination) {
sm->source = source;
sm->destination = destination;
- __sync_fetch_and_add(&sm->version , 1);
+ ATOM_INC(&sm->version);
}
void
diff --git a/skynet-src/skynet_mq.c b/skynet-src/skynet_mq.c
index ba0c61e6..157f33d8 100644
--- a/skynet-src/skynet_mq.c
+++ b/skynet-src/skynet_mq.c
@@ -1,6 +1,7 @@
#include "skynet.h"
#include "skynet_mq.h"
#include "skynet_handle.h"
+#include "spinlock.h"
#include
#include
@@ -18,11 +19,11 @@
#define MQ_OVERLOAD 1024
struct message_queue {
+ struct spinlock lock;
uint32_t handle;
int cap;
int head;
int tail;
- int lock;
int release;
int in_global;
int overload;
@@ -34,19 +35,16 @@ struct message_queue {
struct global_queue {
struct message_queue *head;
struct message_queue *tail;
- int lock;
+ struct spinlock lock;
};
static struct global_queue *Q = NULL;
-#define LOCK(q) while (__sync_lock_test_and_set(&(q)->lock,1)) {}
-#define UNLOCK(q) __sync_lock_release(&(q)->lock);
-
void
skynet_globalmq_push(struct message_queue * queue) {
struct global_queue *q= Q;
- LOCK(q)
+ SPIN_LOCK(q)
assert(queue->next == NULL);
if(q->tail) {
q->tail->next = queue;
@@ -54,14 +52,14 @@ skynet_globalmq_push(struct message_queue * queue) {
} else {
q->head = q->tail = queue;
}
- UNLOCK(q)
+ SPIN_UNLOCK(q)
}
struct message_queue *
skynet_globalmq_pop() {
struct global_queue *q = Q;
- LOCK(q)
+ SPIN_LOCK(q)
struct message_queue *mq = q->head;
if(mq) {
q->head = mq->next;
@@ -71,7 +69,7 @@ skynet_globalmq_pop() {
}
mq->next = NULL;
}
- UNLOCK(q)
+ SPIN_UNLOCK(q)
return mq;
}
@@ -83,7 +81,7 @@ skynet_mq_create(uint32_t handle) {
q->cap = DEFAULT_QUEUE_SIZE;
q->head = 0;
q->tail = 0;
- q->lock = 0;
+ SPIN_INIT(q)
// When the queue is create (always between service create and service init) ,
// set in_global flag to avoid push it to global queue .
// If the service init success, skynet_context_new will call skynet_mq_force_push to push it to global queue.
@@ -100,6 +98,7 @@ skynet_mq_create(uint32_t handle) {
static void
_release(struct message_queue *q) {
assert(q->next == NULL);
+ SPIN_DESTROY(q)
skynet_free(q->queue);
skynet_free(q);
}
@@ -113,11 +112,11 @@ int
skynet_mq_length(struct message_queue *q) {
int head, tail,cap;
- LOCK(q)
+ SPIN_LOCK(q)
head = q->head;
tail = q->tail;
cap = q->cap;
- UNLOCK(q)
+ SPIN_UNLOCK(q)
if (head <= tail) {
return tail - head;
@@ -138,7 +137,7 @@ skynet_mq_overload(struct message_queue *q) {
int
skynet_mq_pop(struct message_queue *q, struct skynet_message *message) {
int ret = 1;
- LOCK(q)
+ SPIN_LOCK(q)
if (q->head != q->tail) {
*message = q->queue[q->head++];
@@ -167,7 +166,7 @@ skynet_mq_pop(struct message_queue *q, struct skynet_message *message) {
q->in_global = 0;
}
- UNLOCK(q)
+ SPIN_UNLOCK(q)
return ret;
}
@@ -190,7 +189,7 @@ expand_queue(struct message_queue *q) {
void
skynet_mq_push(struct message_queue *q, struct skynet_message *message) {
assert(message);
- LOCK(q)
+ SPIN_LOCK(q)
q->queue[q->tail] = *message;
if (++ q->tail >= q->cap) {
@@ -206,25 +205,26 @@ skynet_mq_push(struct message_queue *q, struct skynet_message *message) {
skynet_globalmq_push(q);
}
- UNLOCK(q)
+ SPIN_UNLOCK(q)
}
void
skynet_mq_init() {
struct global_queue *q = skynet_malloc(sizeof(*q));
memset(q,0,sizeof(*q));
+ SPIN_INIT(q);
Q=q;
}
void
skynet_mq_mark_release(struct message_queue *q) {
- LOCK(q)
+ SPIN_LOCK(q)
assert(q->release == 0);
q->release = 1;
if (q->in_global != MQ_IN_GLOBAL) {
skynet_globalmq_push(q);
}
- UNLOCK(q)
+ SPIN_UNLOCK(q)
}
static void
@@ -238,13 +238,13 @@ _drop_queue(struct message_queue *q, message_drop drop_func, void *ud) {
void
skynet_mq_release(struct message_queue *q, message_drop drop_func, void *ud) {
- LOCK(q)
+ SPIN_LOCK(q)
if (q->release) {
- UNLOCK(q)
+ SPIN_UNLOCK(q)
_drop_queue(q, drop_func, ud);
} else {
skynet_globalmq_push(q);
- UNLOCK(q)
+ SPIN_UNLOCK(q)
}
}
diff --git a/skynet-src/skynet_server.c b/skynet-src/skynet_server.c
index 52331193..4972e7a4 100644
--- a/skynet-src/skynet_server.c
+++ b/skynet-src/skynet_server.c
@@ -10,6 +10,8 @@
#include "skynet_monitor.h"
#include "skynet_imp.h"
#include "skynet_log.h"
+#include "spinlock.h"
+#include "atomic.h"
#include
@@ -21,16 +23,18 @@
#ifdef CALLING_CHECK
-#define CHECKCALLING_BEGIN(ctx) assert(__sync_lock_test_and_set(&ctx->calling,1) == 0);
-#define CHECKCALLING_END(ctx) __sync_lock_release(&ctx->calling);
-#define CHECKCALLING_INIT(ctx) ctx->calling = 0;
-#define CHECKCALLING_DECL int calling;
+#define CHECKCALLING_BEGIN(ctx) if (!(spinlock_trylock(&ctx->calling))) { assert(0); }
+#define CHECKCALLING_END(ctx) spinlock_unlock(&ctx->calling);
+#define CHECKCALLING_INIT(ctx) spinlock_init(&ctx->calling);
+#define CHECKCALLING_DESTROY(ctx) spinlock_destroy(&ctx->calling);
+#define CHECKCALLING_DECL struct spinlock calling;
#else
#define CHECKCALLING_BEGIN(ctx)
#define CHECKCALLING_END(ctx)
#define CHECKCALLING_INIT(ctx)
+#define CHECKCALLING_DESTROY(ctx)
#define CHECKCALLING_DECL
#endif
@@ -68,12 +72,12 @@ skynet_context_total() {
static void
context_inc() {
- __sync_fetch_and_add(&G_NODE.total,1);
+ ATOM_INC(&G_NODE.total);
}
static void
context_dec() {
- __sync_fetch_and_sub(&G_NODE.total,1);
+ ATOM_DEC(&G_NODE.total);
}
uint32_t
@@ -179,7 +183,7 @@ skynet_context_newsession(struct skynet_context *ctx) {
void
skynet_context_grab(struct skynet_context *ctx) {
- __sync_add_and_fetch(&ctx->ref,1);
+ ATOM_INC(&ctx->ref);
}
void
@@ -197,13 +201,14 @@ delete_context(struct skynet_context *ctx) {
}
skynet_module_instance_release(ctx->mod, ctx->instance);
skynet_mq_mark_release(ctx->queue);
+ CHECKCALLING_DESTROY(ctx)
skynet_free(ctx);
context_dec();
}
struct skynet_context *
skynet_context_release(struct skynet_context *ctx) {
- if (__sync_sub_and_fetch(&ctx->ref,1) == 0) {
+ if (ATOM_DEC(&ctx->ref) == 0) {
delete_context(ctx);
return NULL;
}
@@ -560,7 +565,7 @@ cmd_logon(struct skynet_context * context, const char * param) {
if (lastf == NULL) {
f = skynet_log_open(context, handle);
if (f) {
- if (!__sync_bool_compare_and_swap(&ctx->logfile, NULL, f)) {
+ if (!ATOM_CAS_POINTER(&ctx->logfile, NULL, f)) {
// logfile opens in other thread, close this one.
fclose(f);
}
@@ -581,7 +586,7 @@ cmd_logoff(struct skynet_context * context, const char * param) {
FILE * f = ctx->logfile;
if (f) {
// logfile may close in other thread
- if (__sync_bool_compare_and_swap(&ctx->logfile, f, NULL)) {
+ if (ATOM_CAS_POINTER(&ctx->logfile, f, NULL)) {
skynet_log_close(context, f, handle);
}
}
diff --git a/skynet-src/skynet_timer.c b/skynet-src/skynet_timer.c
index f23114dc..c9a113ae 100644
--- a/skynet-src/skynet_timer.c
+++ b/skynet-src/skynet_timer.c
@@ -4,6 +4,7 @@
#include "skynet_mq.h"
#include "skynet_server.h"
#include "skynet_handle.h"
+#include "spinlock.h"
#include
#include
@@ -17,9 +18,6 @@
typedef void (*timer_execute_func)(void *ud,void *arg);
-#define LOCK(q) while (__sync_lock_test_and_set(&(q)->lock,1)) {}
-#define UNLOCK(q) __sync_lock_release(&(q)->lock);
-
#define TIME_NEAR_SHIFT 8
#define TIME_NEAR (1 << TIME_NEAR_SHIFT)
#define TIME_LEVEL_SHIFT 6
@@ -45,7 +43,7 @@ struct link_list {
struct timer {
struct link_list near[TIME_NEAR];
struct link_list t[4][TIME_LEVEL];
- int lock;
+ struct spinlock lock;
uint32_t time;
uint32_t current;
uint32_t starttime;
@@ -97,12 +95,12 @@ timer_add(struct timer *T,void *arg,size_t sz,int time) {
struct timer_node *node = (struct timer_node *)skynet_malloc(sizeof(*node)+sz);
memcpy(node+1,arg,sz);
- LOCK(T);
+ SPIN_LOCK(T);
node->expire=time+T->time;
add_node(T,node);
- UNLOCK(T);
+ SPIN_UNLOCK(T);
}
static void
@@ -162,16 +160,16 @@ timer_execute(struct timer *T) {
while (T->near[idx].head.next) {
struct timer_node *current = link_clear(&T->near[idx]);
- UNLOCK(T);
+ SPIN_UNLOCK(T);
// dispatch_list don't need lock T
dispatch_list(current);
- LOCK(T);
+ SPIN_LOCK(T);
}
}
static void
timer_update(struct timer *T) {
- LOCK(T);
+ SPIN_LOCK(T);
// try to dispatch timeout 0 (rare condition)
timer_execute(T);
@@ -181,7 +179,7 @@ timer_update(struct timer *T) {
timer_execute(T);
- UNLOCK(T);
+ SPIN_UNLOCK(T);
}
static struct timer *
@@ -201,7 +199,8 @@ timer_create_timer() {
}
}
- r->lock = 0;
+ SPIN_INIT(r)
+
r->current = 0;
return r;
diff --git a/skynet-src/socket_server.c b/skynet-src/socket_server.c
index 78f9b47b..b2454d2e 100644
--- a/skynet-src/socket_server.c
+++ b/skynet-src/socket_server.c
@@ -2,6 +2,7 @@
#include "socket_server.h"
#include "socket_poll.h"
+#include "atomic.h"
#include
#include
@@ -237,13 +238,13 @@ static int
reserve_id(struct socket_server *ss) {
int i;
for (i=0;ialloc_id), 1);
+ int id = ATOM_INC(&(ss->alloc_id));
if (id < 0) {
- id = __sync_and_and_fetch(&(ss->alloc_id), 0x7fffffff);
+ id = ATOM_AND(&(ss->alloc_id), 0x7fffffff);
}
struct socket *s = &ss->slot[HASH_ID(id)];
if (s->type == SOCKET_TYPE_INVALID) {
- if (__sync_bool_compare_and_swap(&s->type, SOCKET_TYPE_INVALID, SOCKET_TYPE_RESERVE)) {
+ if (ATOM_CAS(&s->type, SOCKET_TYPE_INVALID, SOCKET_TYPE_RESERVE)) {
s->id = id;
s->fd = -1;
return id;
diff --git a/skynet-src/spinlock.h b/skynet-src/spinlock.h
new file mode 100644
index 00000000..d9744c3f
--- /dev/null
+++ b/skynet-src/spinlock.h
@@ -0,0 +1,77 @@
+#ifndef SKYNET_SPINLOCK_H
+#define SKYNET_SPINLOCK_H
+
+#define SPIN_INIT(q) spinlock_init(&(q)->lock);
+#define SPIN_LOCK(q) spinlock_lock(&(q)->lock);
+#define SPIN_UNLOCK(q) spinlock_unlock(&(q)->lock);
+#define SPIN_DESTROY(q) spinlock_destroy(&(q)->lock);
+
+#ifndef USE_PTHREAD_LOCK
+
+struct spinlock {
+ int lock;
+};
+
+static inline void
+spinlock_init(struct spinlock *lock) {
+ lock->lock = 0;
+}
+
+static inline void
+spinlock_lock(struct spinlock *lock) {
+ while (__sync_lock_test_and_set(&lock->lock,1)) {}
+}
+
+static inline int
+spinlock_trylock(struct spinlock *lock) {
+ return __sync_lock_test_and_set(&lock->lock,1) == 0;
+}
+
+static inline void
+spinlock_unlock(struct spinlock *lock) {
+ __sync_lock_release(&lock->lock);
+}
+
+static inline void
+spinlock_destroy(struct spinlock *lock) {
+}
+
+#else
+
+#include
+
+// we use mutex instead of spinlock for some reason
+// you can also replace to pthread_spinlock
+
+struct spinlock {
+ pthread_mutex_t lock;
+};
+
+static inline void
+spinlock_init(struct spinlock *lock) {
+ pthread_mutex_init(&lock->lock, NULL);
+}
+
+static inline void
+spinlock_lock(struct spinlock *lock) {
+ pthread_mutex_lock(&lock->lock);
+}
+
+static inline int
+spinlock_trylock(struct spinlock *lock) {
+ return pthread_mutex_trylock(&lock->lock) == 0;
+}
+
+static inline void
+spinlock_unlock(struct spinlock *lock) {
+ pthread_mutex_unlock(&lock->lock);
+}
+
+static inline void
+spinlock_destroy(struct spinlock *lock) {
+ pthread_mutex_destroy(&lock->lock);
+}
+
+#endif
+
+#endif
From a38a3140dde2e8d20aadbe9dd04b8d4c0a14e37b Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Fri, 14 Aug 2015 17:32:59 +0800
Subject: [PATCH 37/97] error when send to address 0
---
lualib-src/lua-skynet.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/lualib-src/lua-skynet.c b/lualib-src/lua-skynet.c
index c92ff98d..7d75d2ce 100644
--- a/lualib-src/lua-skynet.c
+++ b/lualib-src/lua-skynet.c
@@ -172,6 +172,9 @@ _send(lua_State *L) {
uint32_t dest = (uint32_t)lua_tointeger(L, 1);
const char * dest_string = NULL;
if (dest == 0) {
+ if (lua_type(L,1) == LUA_TNUMBER) {
+ return luaL_error(L, "Invalid service address 0");
+ }
dest_string = get_dest_string(L, 1);
}
From 2583af26d7e5fe58f1f0aef4463d99ae1619a656 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Fri, 14 Aug 2015 23:22:00 +0800
Subject: [PATCH 38/97] add cluster.register and cluster.query
---
examples/cluster1.lua | 13 +++++++------
examples/cluster2.lua | 9 ++++++---
lualib-src/lua-cluster.c | 4 ++--
lualib/cluster.lua | 10 ++++++++++
service/clusterd.lua | 31 +++++++++++++++++++++++++++++--
5 files changed, 54 insertions(+), 13 deletions(-)
diff --git a/examples/cluster1.lua b/examples/cluster1.lua
index d44899ba..0eca6176 100644
--- a/examples/cluster1.lua
+++ b/examples/cluster1.lua
@@ -1,16 +1,17 @@
local skynet = require "skynet"
local cluster = require "cluster"
-require "skynet.manager" -- import skynet.name
local snax = require "snax"
skynet.start(function()
local sdb = skynet.newservice("simpledb")
- skynet.name(".simpledb", sdb)
+ -- register name "sdb" for simpledb, you can use cluster.query() later.
+ -- See cluster2.lua
+ cluster.register("sdb", sdb)
- print(skynet.call(".simpledb", "lua", "SET", "a", "foobar"))
- print(skynet.call(".simpledb", "lua", "SET", "b", "foobar2"))
- print(skynet.call(".simpledb", "lua", "GET", "a"))
- print(skynet.call(".simpledb", "lua", "GET", "b"))
+ print(skynet.call(sdb, "lua", "SET", "a", "foobar"))
+ print(skynet.call(sdb, "lua", "SET", "b", "foobar2"))
+ print(skynet.call(sdb, "lua", "GET", "a"))
+ print(skynet.call(sdb, "lua", "GET", "b"))
cluster.open "db"
cluster.open "db2"
-- unique snax service
diff --git a/examples/cluster2.lua b/examples/cluster2.lua
index 0aef412c..84648567 100644
--- a/examples/cluster2.lua
+++ b/examples/cluster2.lua
@@ -2,15 +2,18 @@ local skynet = require "skynet"
local cluster = require "cluster"
skynet.start(function()
- local proxy = cluster.proxy("db", ".simpledb")
+ -- query name "sdb" of cluster db.
+ local sdb = cluster.query("db", "sdb")
+ print("db.sbd=",sdb)
+ local proxy = cluster.proxy("db", sdb)
local largekey = string.rep("X", 128*1024)
local largevalue = string.rep("R", 100 * 1024)
print(skynet.call(proxy, "lua", "SET", largekey, largevalue))
local v = skynet.call(proxy, "lua", "GET", largekey)
assert(largevalue == v)
- print(cluster.call("db", ".simpledb", "GET", "a"))
- print(cluster.call("db2", ".simpledb", "GET", "b"))
+ print(cluster.call("db", sdb, "GET", "a"))
+ print(cluster.call("db2", sdb, "GET", "b"))
-- test snax service
local pingserver = cluster.snax("db", "pingserver")
diff --git a/lualib-src/lua-cluster.c b/lualib-src/lua-cluster.c
index e35615c7..6ee1e69b 100644
--- a/lualib-src/lua-cluster.c
+++ b/lualib-src/lua-cluster.c
@@ -219,8 +219,8 @@ unpackreq_number(lua_State *L, const uint8_t * buf, int sz) {
static int
unpackmreq_number(lua_State *L, const uint8_t * buf, int sz) {
- if (sz != 15) {
- return luaL_error(L, "Invalid cluster message size %d (multi req must be 15)", sz);
+ if (sz != 13) {
+ return luaL_error(L, "Invalid cluster message size %d (multi req must be 13)", sz);
}
uint32_t address = unpack_uint32(buf+1);
uint32_t session = unpack_uint32(buf+5);
diff --git a/lualib/cluster.lua b/lualib/cluster.lua
index e4407f06..dba8f318 100644
--- a/lualib/cluster.lua
+++ b/lualib/cluster.lua
@@ -33,6 +33,16 @@ function cluster.snax(node, name, address)
return snax.bind(handle, name)
end
+function cluster.register(name, addr)
+ assert(type(name) == "string")
+ assert(addr == nil or type(addr) == "number")
+ return skynet.call(clusterd, "lua", "register", name, addr)
+end
+
+function cluster.query(node, name)
+ return skynet.call(clusterd, "lua", "req", node, 0, skynet.pack(name))
+end
+
skynet.init(function()
clusterd = skynet.uniqueservice("clusterd")
end)
diff --git a/service/clusterd.lua b/service/clusterd.lua
index b3c74722..22d5e9f0 100644
--- a/service/clusterd.lua
+++ b/service/clusterd.lua
@@ -97,6 +97,21 @@ function command.proxy(source, node, name)
skynet.ret(skynet.pack(proxy[fullname]))
end
+local register_name = {}
+
+function command.register(source, name, addr)
+ assert(register_name[name] == nil)
+ addr = addr or source
+ local old_name = register_name[addr]
+ if old_name then
+ register_name[old_name] = nil
+ end
+ register_name[addr] = name
+ register_name[name] = addr
+ skynet.ret(nil)
+ skynet.error(string.format("Register [%s] :%08x", name, addr))
+end
+
local large_request = {}
function command.socket(source, subcmd, fd, msg)
@@ -122,8 +137,20 @@ function command.socket(source, subcmd, fd, msg)
return
end
end
- local ok , msg, sz = pcall(skynet.rawcall, addr, "lua", msg, sz)
- local response
+ local ok, response
+ if addr == 0 then
+ local name = skynet.unpack(msg, sz)
+ local addr = register_name[name]
+ if addr then
+ ok = true
+ msg, sz = skynet.pack(addr)
+ else
+ ok = false
+ msg = "name not found"
+ end
+ else
+ ok , msg, sz = pcall(skynet.rawcall, addr, "lua", msg, sz)
+ end
if ok then
response = cluster.packresponse(session, true, msg, sz)
if type(response) == "table" then
From 1b53e6e28de7cda4dd3df8d974525a25e406e486 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Mon, 17 Aug 2015 11:21:20 +0800
Subject: [PATCH 39/97] Release alpha 10
---
HISTORY.md | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/HISTORY.md b/HISTORY.md
index a970b7c2..48c7a069 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -1,10 +1,20 @@
+v1.0.0-alpha10 (2015-8-17)
+-----------
+* Remove the size limit of cluster RPC message.
+* Remove the size limit of local message.
+* Add cluster.query and clsuter.register.
+* Add an option of pthread mutex lock.
+* Add skynet.core.intcommand to optimize skynet.sleep etc.
+* Fix a memory leak bug in lua shared proto.
+* snax.msgserver use string instead of lightuserdata/size.
+* Remove some unused api in netpack.
+* Raise error when skynet.send to 0.
+
v1.0.0-alpha9 (2015-8-10)
-----------
* Improve lua serialization , support pairs metamethod.
* Bugfix : sproto (See commits log of sproto)
* Add user log service support (In config)
-* Remove the size limit of cluster RPC message.
-* Remove the size limit of local message.
* Other minor bugfix (See commits log)
v1.0.0-alpha8 (2015-6-29)
From c0862d8445bf6e20f104b0e171e8e03ca98c58e5 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Fri, 21 Aug 2015 11:41:01 +0800
Subject: [PATCH 40/97] add global share string table
---
3rd/lua/Makefile | 2 +-
3rd/lua/lapi.c | 4 +-
3rd/lua/lgc.c | 3 +-
3rd/lua/lstring.c | 224 +++++++++++++++++++++++++++++++++++++-
3rd/lua/lstring.h | 5 +
3rd/lua/luaconf.h | 1 +
lualib-src/lua-memory.c | 10 ++
service/bootstrap.lua | 4 +
service/debug_console.lua | 19 ++++
skynet-src/luashrtbl.h | 17 +++
skynet-src/skynet_main.c | 4 +
11 files changed, 287 insertions(+), 6 deletions(-)
create mode 100644 skynet-src/luashrtbl.h
diff --git a/3rd/lua/Makefile b/3rd/lua/Makefile
index 6c680538..ddf7b349 100644
--- a/3rd/lua/Makefile
+++ b/3rd/lua/Makefile
@@ -19,7 +19,7 @@ SYSCFLAGS=
SYSLDFLAGS=
SYSLIBS=
-MYCFLAGS=
+MYCFLAGS=-I../../skynet-src
MYLDFLAGS=
MYLIBS=
MYOBJS=
diff --git a/3rd/lua/lapi.c b/3rd/lua/lapi.c
index 953a304b..3f47f7ee 100644
--- a/3rd/lua/lapi.c
+++ b/3rd/lua/lapi.c
@@ -1000,7 +1000,7 @@ static Proto * cloneproto (lua_State *L, const Proto *src) {
const TValue *s=&src->k[i];
TValue *o=&f->k[i];
if (ttisstring(s)) {
- TString * str = luaS_newlstr(L,svalue(s),vslen(s));
+ TString * str = luaS_clonestring(L,tsvalue(s));
setsvalue2n(L,o,str);
} else {
setobj(L,o,s);
@@ -1288,7 +1288,7 @@ static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) {
StkId fi = index2addr(L, fidx);
api_check(L, ttisLclosure(fi), "Lua function expected");
f = clLvalue(fi);
- api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index");
+ api_check(L, (1 <= n && n <= f->p->sp->sizeupvalues), "invalid upvalue index");
if (pf) *pf = f;
return &f->upvals[n - 1]; /* get its upvalue pointer */
}
diff --git a/3rd/lua/lgc.c b/3rd/lua/lgc.c
index e73c58bf..a1ce0245 100644
--- a/3rd/lua/lgc.c
+++ b/3rd/lua/lgc.c
@@ -188,7 +188,8 @@ void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) {
void luaC_fix (lua_State *L, GCObject *o) {
global_State *g = G(L);
- lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */
+ if (g->allgc != o)
+ return; /* if object is not 1st in 'allgc' list, it is in global short string table */
white2gray(o); /* they will be gray forever */
g->allgc = o->next; /* remove object from 'allgc' list */
o->next = g->fixedgc; /* link it to 'fixedgc' list */
diff --git a/3rd/lua/lstring.c b/3rd/lua/lstring.c
index 5e0e3c40..dd36eb87 100644
--- a/3rd/lua/lstring.c
+++ b/3rd/lua/lstring.c
@@ -148,10 +148,9 @@ void luaS_remove (lua_State *L, TString *ts) {
/*
** checks whether short string exists and reuses it or creates a new one
*/
-static TString *internshrstr (lua_State *L, const char *str, size_t l) {
+static TString *queryshrstr (lua_State *L, const char *str, size_t l, unsigned int h) {
TString *ts;
global_State *g = G(L);
- unsigned int h = luaS_hash(str, l, g->seed);
TString **list = &g->strt.hash[lmod(h, g->strt.size)];
for (ts = *list; ts != NULL; ts = ts->u.hnext) {
if (l == ts->shrlen &&
@@ -162,6 +161,13 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
return ts;
}
}
+ return NULL;
+}
+
+static TString *addshrstr (lua_State *L, const char *str, size_t l, unsigned int h) {
+ TString *ts;
+ global_State *g = G(L);
+ TString **list = &g->strt.hash[lmod(h, g->strt.size)];
if (g->strt.nuse >= g->strt.size && g->strt.size <= MAX_INT/2) {
luaS_resize(L, g->strt.size * 2);
list = &g->strt.hash[lmod(h, g->strt.size)]; /* recompute with new size */
@@ -174,6 +180,7 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
return ts;
}
+static TString *internshrstr (lua_State *L, const char *str, size_t l);
/*
** new string (with explicit length)
@@ -224,3 +231,216 @@ Udata *luaS_newudata (lua_State *L, size_t s) {
return u;
}
+/*
+ * global shared table
+ */
+
+#include "rwlock.h"
+#include "atomic.h"
+#include
+
+#define SHRSTR_SLOT 0x10000
+#define HASH_NODE(h) ((h) % SHRSTR_SLOT)
+
+struct shrmap_slot {
+ struct rwlock lock;
+ TString *str;
+};
+
+struct shrmap {
+ struct shrmap_slot h[SHRSTR_SLOT];
+ int n;
+};
+
+static struct shrmap *SSM = NULL;
+
+LUA_API void
+luaS_initshr() {
+ struct shrmap * s = malloc(sizeof(*s));
+ memset(s, 0, sizeof(*s));
+ int i;
+ for (i=0;ih[i].lock);
+ }
+ SSM = s;
+}
+
+LUA_API void
+luaS_exitshr() {
+ int i;
+ for (i=0;ih[i].str;
+ while (str) {
+ TString * next = str->u.hnext;
+ free(str);
+ str = next;
+ }
+ }
+ free(SSM);
+}
+
+static TString *
+query_string(unsigned int h, const char *str, lu_byte l) {
+ struct shrmap_slot *s = &SSM->h[HASH_NODE(h)];
+ rwlock_rlock(&s->lock);
+ TString *ts = s->str;
+ while (ts) {
+ if (ts->hash == h &&
+ ts->shrlen == l &&
+ memcmp(str, ts+1, l) == 0) {
+ break;
+ }
+ ts = ts->u.hnext;
+ }
+ rwlock_runlock(&s->lock);
+ return ts;
+}
+
+static TString *
+query_ptr(TString *t) {
+ unsigned int h = t->hash;
+ struct shrmap_slot *s = &SSM->h[HASH_NODE(h)];
+ rwlock_rlock(&s->lock);
+ TString *ts = s->str;
+ while (ts) {
+ if (ts == t)
+ break;
+ ts = ts->u.hnext;
+ }
+ rwlock_runlock(&s->lock);
+ return ts;
+}
+
+static TString *
+new_string(unsigned int h, const char *str, lu_byte l) {
+ size_t sz = sizelstring(l);
+ TString *ts = malloc(sz);
+ memset(ts, 0, sz);
+ ts->tt = LUA_TSHRSTR;
+ ts->hash = h;
+ ts->shrlen = l;
+ memcpy(ts+1, str, l);
+ return ts;
+}
+
+static TString *
+add_string(unsigned int h, const char *str, lu_byte l) {
+ TString * tmp = new_string(h, str, l);
+ struct shrmap_slot *s = &SSM->h[HASH_NODE(h)];
+ rwlock_wlock(&s->lock);
+ TString *ts = s->str;
+ while (ts) {
+ if (ts->hash == h &&
+ ts->shrlen == l &&
+ memcmp(str, ts+1, l) == 0) {
+ break;
+ }
+ ts = ts->u.hnext;
+ }
+ if (ts == NULL) {
+ ts = tmp;
+ ts->u.hnext = s->str;
+ s->str = ts;
+ tmp = NULL;
+ }
+ rwlock_wunlock(&s->lock);
+ if (tmp) {
+ // string is create by other thread, so free tmp
+ free(tmp);
+ }
+ return ts;
+}
+
+static TString *
+internshrstr (lua_State *L, const char *str, size_t l) {
+ TString *ts;
+ global_State *g = G(L);
+ unsigned int h = luaS_hash(str, l, g->seed);
+ unsigned int h0;
+ // lookup global state of this L first
+ ts = queryshrstr (L, str, l, h);
+ if (ts)
+ return ts;
+ // lookup SSM again
+ h0 = luaS_hash(str, l, 0);
+ ts = query_string(h0, str, l);
+ if (ts)
+ return ts;
+ // If SSM->n greate than 0, add it to SSM
+ if (SSM->n > 0) {
+ ATOM_DEC(&SSM->n);
+ return add_string(h0, str, l);
+ }
+ // Else add it to global state (local)
+ return addshrstr (L, str, l, h);
+}
+
+LUA_API void
+luaS_expandshr(int n) {
+ ATOM_ADD(&SSM->n, n);
+}
+
+LUAI_FUNC TString *
+luaS_clonestring(lua_State *L, TString *ts) {
+ unsigned int h;
+ int l;
+ const char * str = getaddrstr(ts);
+ global_State *g = G(L);
+ TString *result;
+ if (ts->tt == LUA_TLNGSTR)
+ return luaS_newlstr(L, str, ts->u.lnglen);
+ // look up global state of this L first
+ l = ts->shrlen;
+ h = luaS_hash(str, l, g->seed);
+ result = queryshrstr (L, str, l, h);
+ if (result)
+ return result;
+ // look up SSM by ptr
+ result = query_ptr(ts);
+ if (result)
+ return result;
+ // ts is not in SSM, so recalc hash, and add it to SSM
+ h = luaS_hash(str, l, 0);
+ return add_string(h, str, l);
+}
+
+struct slotinfo {
+ int len;
+ int size;
+};
+
+static void
+getslot(struct shrmap_slot *s, struct slotinfo *info) {
+ memset(info, 0, sizeof(*info));
+ rwlock_rlock(&s->lock);
+ TString *ts = s->str;
+ while (ts) {
+ ++info->len;
+ info->size += ts->shrlen;
+ ts = ts->u.hnext;
+ }
+ rwlock_runlock(&s->lock);
+}
+
+LUA_API int
+luaS_shrinfo(lua_State *L) {
+ struct slotinfo total;
+ struct slotinfo tmp;
+ memset(&total, 0, sizeof(total));
+ int i;
+ int len = 0;
+ for (i=0;ih[i];
+ getslot(s, &tmp);
+ len += tmp.len;
+ if (tmp.len > total.len) {
+ total.len = tmp.len;
+ }
+ total.size += tmp.size;
+ }
+ lua_pushinteger(L, len);
+ lua_pushinteger(L, total.size);
+ lua_pushinteger(L, total.len);
+ lua_pushinteger(L, SSM->n);
+ return 4;
+}
diff --git a/3rd/lua/lstring.h b/3rd/lua/lstring.h
index e746f5fc..b3cfa1b7 100644
--- a/3rd/lua/lstring.h
+++ b/3rd/lua/lstring.h
@@ -43,5 +43,10 @@ LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s);
LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
LUAI_FUNC TString *luaS_new (lua_State *L, const char *str);
+LUA_API void luaS_initshr();
+LUA_API void luaS_exitshr();
+LUA_API void luaS_expandshr(int n);
+LUAI_FUNC TString *luaS_clonestring(lua_State *L, TString *);
+LUA_API int luaS_shrinfo(lua_State *L);
#endif
diff --git a/3rd/lua/luaconf.h b/3rd/lua/luaconf.h
index 7cfa4faf..5e88dcb0 100644
--- a/3rd/lua/luaconf.h
+++ b/3rd/lua/luaconf.h
@@ -11,6 +11,7 @@
#include
#include
+#define LUA_USE_APICHECK
/*
** ===================================================================
diff --git a/lualib-src/lua-memory.c b/lualib-src/lua-memory.c
index 67a3acf6..a3afecfc 100644
--- a/lualib-src/lua-memory.c
+++ b/lualib-src/lua-memory.c
@@ -2,6 +2,7 @@
#include
#include "malloc_hook.h"
+#include "luashrtbl.h"
static int
ltotal(lua_State *L) {
@@ -33,6 +34,13 @@ ldump(lua_State *L) {
return 0;
}
+static int
+lexpandshrtbl(lua_State *L) {
+ int n = luaL_checkinteger(L, 1);
+ luaS_expandshr(n);
+ return 0;
+}
+
int
luaopen_memory(lua_State *L) {
luaL_checkversion(L);
@@ -43,6 +51,8 @@ luaopen_memory(lua_State *L) {
{ "dumpinfo", ldumpinfo },
{ "dump", ldump },
{ "info", dump_mem_lua },
+ { "ssinfo", luaS_shrinfo },
+ { "ssexpand", lexpandshrtbl },
{ NULL, NULL },
};
diff --git a/service/bootstrap.lua b/service/bootstrap.lua
index 269654c3..db8d8581 100644
--- a/service/bootstrap.lua
+++ b/service/bootstrap.lua
@@ -1,8 +1,12 @@
local skynet = require "skynet"
local harbor = require "skynet.harbor"
require "skynet.manager" -- import skynet.launch, ...
+local memory = require "memory"
skynet.start(function()
+ local sharestring = tonumber(skynet.getenv "sharestring")
+ memory.ssexpand(sharestring or 4096)
+
local standalone = skynet.getenv "standalone"
local launcher = assert(skynet.launch("snlua","launcher"))
diff --git a/service/debug_console.lua b/service/debug_console.lua
index 97b35806..37b20c30 100644
--- a/service/debug_console.lua
+++ b/service/debug_console.lua
@@ -3,6 +3,7 @@ local codecache = require "skynet.codecache"
local core = require "skynet.core"
local socket = require "socket"
local snax = require "snax"
+local memory = require "memory"
local port = tonumber(...)
local COMMAND = {}
@@ -130,6 +131,8 @@ function COMMAND.help()
log = "launch a new lua service with log",
debug = "debug address : debug a lua service",
signal = "signal address sig",
+ cmem = "Show C memory info",
+ shrtbl = "Show shared short string table info",
}
end
@@ -258,3 +261,19 @@ function COMMAND.signal(address, sig)
core.command("SIGNAL", address)
end
end
+
+function COMMAND.cmem()
+ local info = memory.info()
+ local tmp = {}
+ for k,v in pairs(info) do
+ tmp[skynet.address(k)] = v
+ end
+ return tmp
+end
+
+function COMMAND.shrtbl()
+ local n, total, longest, space = memory.ssinfo()
+ return { n = n, total = total, longest = longest, space = space }
+end
+
+
diff --git a/skynet-src/luashrtbl.h b/skynet-src/luashrtbl.h
new file mode 100644
index 00000000..6f566038
--- /dev/null
+++ b/skynet-src/luashrtbl.h
@@ -0,0 +1,17 @@
+#ifndef LUA_SHORT_STRING_TABLE_H
+#define LUA_SHORT_STRING_TABLE_H
+
+#ifndef DISABLE_SHORT_STRING
+
+#include "lstring.h"
+
+#else
+
+static inline int luaS_shrinfo(lua_State *L) { return 0; }
+static inline void luaS_initshr() {}
+static inline void luaS_exitshr() {}
+static inline void luaS_expandshr(int n);
+
+#endif
+
+#endif
diff --git a/skynet-src/skynet_main.c b/skynet-src/skynet_main.c
index 59e344f8..eb6f4429 100644
--- a/skynet-src/skynet_main.c
+++ b/skynet-src/skynet_main.c
@@ -3,6 +3,7 @@
#include "skynet_imp.h"
#include "skynet_env.h"
#include "skynet_server.h"
+#include "luashrtbl.h"
#include
#include
@@ -105,6 +106,8 @@ main(int argc, char *argv[]) {
"usage: skynet configfilename\n");
return 1;
}
+
+ luaS_initshr();
skynet_globalinit();
skynet_env_init();
@@ -139,6 +142,7 @@ main(int argc, char *argv[]) {
skynet_start(&config);
skynet_globalexit();
+ luaS_exitshr();
return 0;
}
From 9acce94464d162da93f6aea7dd7c31727feaedb3 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Fri, 21 Aug 2015 13:55:43 +0800
Subject: [PATCH 41/97] disable lua apicheck
---
3rd/lua/luaconf.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/3rd/lua/luaconf.h b/3rd/lua/luaconf.h
index 5e88dcb0..7cfa4faf 100644
--- a/3rd/lua/luaconf.h
+++ b/3rd/lua/luaconf.h
@@ -11,7 +11,6 @@
#include
#include
-#define LUA_USE_APICHECK
/*
** ===================================================================
From bb6d5d826ec029a025d2bb5525a30d166e098df9 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Fri, 21 Aug 2015 15:59:51 +0800
Subject: [PATCH 42/97] add TString struct size
---
3rd/lua/lstring.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/3rd/lua/lstring.c b/3rd/lua/lstring.c
index dd36eb87..3516747a 100644
--- a/3rd/lua/lstring.c
+++ b/3rd/lua/lstring.c
@@ -416,7 +416,7 @@ getslot(struct shrmap_slot *s, struct slotinfo *info) {
TString *ts = s->str;
while (ts) {
++info->len;
- info->size += ts->shrlen;
+ info->size += sizelstring(ts->shrlen);
ts = ts->u.hnext;
}
rwlock_runlock(&s->lock);
From eb587c63d3897f5f3a5f14b07e125cea910b79af Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Fri, 21 Aug 2015 19:42:09 +0800
Subject: [PATCH 43/97] fix issue #327
---
skynet-src/skynet_server.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/skynet-src/skynet_server.c b/skynet-src/skynet_server.c
index 4972e7a4..64258a92 100644
--- a/skynet-src/skynet_server.c
+++ b/skynet-src/skynet_server.c
@@ -674,7 +674,9 @@ int
skynet_send(struct skynet_context * context, uint32_t source, uint32_t destination , int type, int session, void * data, size_t sz) {
if ((sz & MESSAGE_TYPE_MASK) != sz) {
skynet_error(context, "The message to %x is too large", destination);
- skynet_free(data);
+ if (type & PTYPE_TAG_DONTCOPY) {
+ skynet_free(data);
+ }
return -1;
}
_filter_args(context, type, &session, (void **)&data, &sz);
From 010d1c1d4f9826de9f56868ef13faba1261d59d8 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Mon, 24 Aug 2015 11:50:40 +0800
Subject: [PATCH 44/97] avoid dead loop
---
service-src/service_harbor.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/service-src/service_harbor.c b/service-src/service_harbor.c
index 5ff618f1..ed05190b 100644
--- a/service-src/service_harbor.c
+++ b/service-src/service_harbor.c
@@ -317,8 +317,11 @@ forward_local_messsage(struct harbor *h, void *msg, int sz) {
destination = (destination & HANDLE_MASK) | ((uint32_t)h->id << HANDLE_REMOTE_SHIFT);
if (skynet_send(h->ctx, header.source, destination, type, (int)header.session, (void *)msg, sz-HEADER_COOKIE_LENGTH) < 0) {
- skynet_send(h->ctx, destination, header.source , PTYPE_ERROR, (int)header.session, NULL, 0);
- skynet_error(h->ctx, "Unknown destination :%x from :%x", destination, header.source);
+ if (type != PTYPE_ERROR) {
+ // don't need report error when type is error
+ skynet_send(h->ctx, destination, header.source , PTYPE_ERROR, (int)header.session, NULL, 0);
+ }
+ skynet_error(h->ctx, "Unknown destination :%x from :%x type(%d)", destination, header.source, type);
}
}
From 9b0e496afe2781c5f01bbbbd90db9a753fcd38e1 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Thu, 27 Aug 2015 13:49:31 +0800
Subject: [PATCH 45/97] minor amend
---
3rd/lua/README | 7 ++++---
3rd/lua/lstring.h | 2 ++
skynet-src/luashrtbl.h | 5 ++---
3 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/3rd/lua/README b/3rd/lua/README
index a77dc6bf..efb71d70 100644
--- a/3rd/lua/README
+++ b/3rd/lua/README
@@ -1,5 +1,6 @@
This is a modify version of lua 5.3.1 (http://www.lua.org/ftp/lua-5.3.1.tar.gz) .
-For detail : http://lua-users.org/lists/lua-l/2014-03/msg00489.html
-
-
+For detail ,
+ Shared Proto : http://lua-users.org/lists/lua-l/2014-03/msg00489.html
+ Shared short string table : http://blog.codingnow.com/2015/08/lua_vm_share_string.html
+
\ No newline at end of file
diff --git a/3rd/lua/lstring.h b/3rd/lua/lstring.h
index b3cfa1b7..a28ff0a0 100644
--- a/3rd/lua/lstring.h
+++ b/3rd/lua/lstring.h
@@ -43,6 +43,8 @@ LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s);
LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
LUAI_FUNC TString *luaS_new (lua_State *L, const char *str);
+#define ENABLE_SHORT_STRING_TABLE
+
LUA_API void luaS_initshr();
LUA_API void luaS_exitshr();
LUA_API void luaS_expandshr(int n);
diff --git a/skynet-src/luashrtbl.h b/skynet-src/luashrtbl.h
index 6f566038..824a0c85 100644
--- a/skynet-src/luashrtbl.h
+++ b/skynet-src/luashrtbl.h
@@ -1,11 +1,10 @@
#ifndef LUA_SHORT_STRING_TABLE_H
#define LUA_SHORT_STRING_TABLE_H
-#ifndef DISABLE_SHORT_STRING
-
#include "lstring.h"
-#else
+// If you use modified lua, this macro would be defined in lstring.h
+#ifndef ENABLE_SHORT_STRING_TABLE
static inline int luaS_shrinfo(lua_State *L) { return 0; }
static inline void luaS_initshr() {}
From 1bfddda435e0c7952d1d6732a35c659364d6782d Mon Sep 17 00:00:00 2001
From: snail
Date: Thu, 27 Aug 2015 18:04:56 +0800
Subject: [PATCH 46/97] uncomplete buffer not free
'uncomplete' buffer not freed in clear
---
lualib-src/lua-netpack.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/lualib-src/lua-netpack.c b/lualib-src/lua-netpack.c
index 193938b1..6e601e07 100644
--- a/lualib-src/lua-netpack.c
+++ b/lualib-src/lua-netpack.c
@@ -49,6 +49,7 @@ struct queue {
static void
clear_list(struct uncomplete * uc) {
while (uc) {
+ skynet_free(uc->pack.buffer);
void * tmp = uc;
uc = uc->next;
skynet_free(tmp);
From 633e5fbe324fefeb4642ebf650cd01f185bbc91b Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Sat, 29 Aug 2015 15:24:24 +0800
Subject: [PATCH 47/97] fix issue #331
---
3rd/lua/lstring.c | 27 ++++++++++++---------------
1 file changed, 12 insertions(+), 15 deletions(-)
diff --git a/3rd/lua/lstring.c b/3rd/lua/lstring.c
index 3516747a..5046624d 100644
--- a/3rd/lua/lstring.c
+++ b/3rd/lua/lstring.c
@@ -252,36 +252,33 @@ struct shrmap {
int n;
};
-static struct shrmap *SSM = NULL;
+static struct shrmap SSM;
LUA_API void
luaS_initshr() {
- struct shrmap * s = malloc(sizeof(*s));
- memset(s, 0, sizeof(*s));
+ struct shrmap * s = &SSM;
int i;
for (i=0;ih[i].lock);
}
- SSM = s;
}
LUA_API void
luaS_exitshr() {
int i;
for (i=0;ih[i].str;
+ TString *str = SSM.h[i].str;
while (str) {
TString * next = str->u.hnext;
free(str);
str = next;
}
}
- free(SSM);
}
static TString *
query_string(unsigned int h, const char *str, lu_byte l) {
- struct shrmap_slot *s = &SSM->h[HASH_NODE(h)];
+ struct shrmap_slot *s = &SSM.h[HASH_NODE(h)];
rwlock_rlock(&s->lock);
TString *ts = s->str;
while (ts) {
@@ -299,7 +296,7 @@ query_string(unsigned int h, const char *str, lu_byte l) {
static TString *
query_ptr(TString *t) {
unsigned int h = t->hash;
- struct shrmap_slot *s = &SSM->h[HASH_NODE(h)];
+ struct shrmap_slot *s = &SSM.h[HASH_NODE(h)];
rwlock_rlock(&s->lock);
TString *ts = s->str;
while (ts) {
@@ -326,7 +323,7 @@ new_string(unsigned int h, const char *str, lu_byte l) {
static TString *
add_string(unsigned int h, const char *str, lu_byte l) {
TString * tmp = new_string(h, str, l);
- struct shrmap_slot *s = &SSM->h[HASH_NODE(h)];
+ struct shrmap_slot *s = &SSM.h[HASH_NODE(h)];
rwlock_wlock(&s->lock);
TString *ts = s->str;
while (ts) {
@@ -366,9 +363,9 @@ internshrstr (lua_State *L, const char *str, size_t l) {
ts = query_string(h0, str, l);
if (ts)
return ts;
- // If SSM->n greate than 0, add it to SSM
- if (SSM->n > 0) {
- ATOM_DEC(&SSM->n);
+ // If SSM.n greate than 0, add it to SSM
+ if (SSM.n > 0) {
+ ATOM_DEC(&SSM.n);
return add_string(h0, str, l);
}
// Else add it to global state (local)
@@ -377,7 +374,7 @@ internshrstr (lua_State *L, const char *str, size_t l) {
LUA_API void
luaS_expandshr(int n) {
- ATOM_ADD(&SSM->n, n);
+ ATOM_ADD(&SSM.n, n);
}
LUAI_FUNC TString *
@@ -430,7 +427,7 @@ luaS_shrinfo(lua_State *L) {
int i;
int len = 0;
for (i=0;ih[i];
+ struct shrmap_slot *s = &SSM.h[i];
getslot(s, &tmp);
len += tmp.len;
if (tmp.len > total.len) {
@@ -441,6 +438,6 @@ luaS_shrinfo(lua_State *L) {
lua_pushinteger(L, len);
lua_pushinteger(L, total.size);
lua_pushinteger(L, total.len);
- lua_pushinteger(L, SSM->n);
+ lua_pushinteger(L, SSM.n);
return 4;
}
From 4f665d2469e5f278835ea388a76f95e8dadc22d1 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Sun, 30 Aug 2015 12:13:23 +0800
Subject: [PATCH 48/97] init global string table, See issue #331
---
3rd/lua/lua.c | 5 ++++-
3rd/lua/luac.c | 2 ++
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/3rd/lua/lua.c b/3rd/lua/lua.c
index 7a47582c..c6e81a55 100644
--- a/3rd/lua/lua.c
+++ b/3rd/lua/lua.c
@@ -18,6 +18,7 @@
#include "lauxlib.h"
#include "lualib.h"
+#include "lstring.h"
#if !defined(LUA_PROMPT)
@@ -596,7 +597,9 @@ static int pmain (lua_State *L) {
int main (int argc, char **argv) {
int status, result;
- lua_State *L = luaL_newstate(); /* create state */
+ lua_State *L;
+ luaS_initshr(); /* init global short string table */
+ L = luaL_newstate(); /* create state */
if (L == NULL) {
l_message(argv[0], "cannot create state: not enough memory");
return EXIT_FAILURE;
diff --git a/3rd/lua/luac.c b/3rd/lua/luac.c
index 0ff987b4..86d47518 100644
--- a/3rd/lua/luac.c
+++ b/3rd/lua/luac.c
@@ -21,6 +21,7 @@
#include "lobject.h"
#include "lstate.h"
#include "lundump.h"
+#include "lstring.h"
static void PrintFunction(const Proto* f, int full);
#define luaU_print PrintFunction
@@ -195,6 +196,7 @@ int main(int argc, char* argv[])
int i=doargs(argc,argv);
argc-=i; argv+=i;
if (argc<=0) usage("no input files given");
+ luaS_initshr();
L=luaL_newstate();
if (L==NULL) fatal("cannot create state: not enough memory");
lua_pushcfunction(L,&pmain);
From bad3472124e0dce5ca8ff76691e2bafe18b787ae Mon Sep 17 00:00:00 2001
From: snail
Date: Sun, 30 Aug 2015 16:47:34 +0800
Subject: [PATCH 49/97] 'response' not released
'response' not released after src service died, and defined error.
---
lualib/skynet.lua | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/lualib/skynet.lua b/lualib/skynet.lua
index e4f46908..56d62e6c 100644
--- a/lualib/skynet.lua
+++ b/lualib/skynet.lua
@@ -186,10 +186,12 @@ function suspend(co, result, command, param, size)
error(debug.traceback(co))
end
local f = param
- local function response(ok, ...)
+ local response
+ response = function(ok, ...)
if ok == "TEST" then
if dead_service[co_address] then
release_watching(co_address)
+ unresponse[response] = nil
f = false
return false
else
@@ -224,7 +226,7 @@ function suspend(co, result, command, param, size)
return ret
end
watching_service[co_address] = watching_service[co_address] + 1
- session_response[co] = response
+ session_response[co] = true
unresponse[response] = true
return suspend(co, coroutine.resume(co, response))
elseif command == "EXIT" then
From 7f9c3c8c9a99b87adff4f3d732b2b9bf905b4d0b Mon Sep 17 00:00:00 2001
From: snail
Date: Sun, 30 Aug 2015 18:17:41 +0800
Subject: [PATCH 50/97] local function is better
local function is the same as " local a; a = function"
---
lualib/skynet.lua | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/lualib/skynet.lua b/lualib/skynet.lua
index 56d62e6c..554d8ff8 100644
--- a/lualib/skynet.lua
+++ b/lualib/skynet.lua
@@ -186,8 +186,7 @@ function suspend(co, result, command, param, size)
error(debug.traceback(co))
end
local f = param
- local response
- response = function(ok, ...)
+ local function response(ok, ...)
if ok == "TEST" then
if dead_service[co_address] then
release_watching(co_address)
From 7797de85b457cf6f724748804a3801f6b5c5a68a Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Mon, 31 Aug 2015 16:36:57 +0800
Subject: [PATCH 51/97] bugfix: See PR #332
---
service/sharedatad.lua | 1 +
1 file changed, 1 insertion(+)
diff --git a/service/sharedatad.lua b/service/sharedatad.lua
index a7e8d427..363f59ef 100644
--- a/service/sharedatad.lua
+++ b/service/sharedatad.lua
@@ -123,6 +123,7 @@ function CMD.monitor(name, obj)
if n > pool_count[name].threshold then
n = n - check_watch(v.watch)
pool_count[name].threshold = n * 2
+ pool_count[name].n = n
end
table.insert(v.watch, skynet.response())
From 6c33f7bc44d0eafe743e5490af3b1e5d86727c45 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Fri, 4 Sep 2015 12:14:09 +0800
Subject: [PATCH 52/97] see pr #332
---
service/sharedatad.lua | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/service/sharedatad.lua b/service/sharedatad.lua
index 363f59ef..d76fd115 100644
--- a/service/sharedatad.lua
+++ b/service/sharedatad.lua
@@ -118,13 +118,12 @@ function CMD.monitor(name, obj)
return v.obj
end
- local n = pool_count[name].n
- pool_count[name].n = n + 1
+ local n = pool_count[name].n + 1
if n > pool_count[name].threshold then
n = n - check_watch(v.watch)
pool_count[name].threshold = n * 2
- pool_count[name].n = n
end
+ pool_count[name].n = n
table.insert(v.watch, skynet.response())
From 846d55eaef0d8e64338ecf323a51718611186d6f Mon Sep 17 00:00:00 2001
From: sanikoyes
Date: Mon, 14 Sep 2015 18:03:04 +0800
Subject: [PATCH 53/97] add missing luaS_exitshr call
---
3rd/lua/lua.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/3rd/lua/lua.c b/3rd/lua/lua.c
index c6e81a55..825d7c21 100644
--- a/3rd/lua/lua.c
+++ b/3rd/lua/lua.c
@@ -611,6 +611,7 @@ int main (int argc, char **argv) {
result = lua_toboolean(L, -1); /* get result */
report(L, status);
lua_close(L);
+ luaS_exitshr();
return (result && status == LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE;
}
From b8f419eb691f64bd3c33ff9836549d245d081fb7 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Tue, 15 Sep 2015 14:52:30 +0800
Subject: [PATCH 54/97] more error message for socket, and close listen socket
when reach limit of open files. See Issue #339
---
lualib/snax/gateserver.lua | 19 +++++++++++++------
lualib/socket.lua | 13 ++++++++-----
skynet-src/skynet_socket.c | 8 ++++++--
skynet-src/socket_server.c | 37 +++++++++++++++++++++++++++++--------
4 files changed, 56 insertions(+), 21 deletions(-)
diff --git a/lualib/snax/gateserver.lua b/lualib/snax/gateserver.lua
index dfce2fa9..68f77b58 100644
--- a/lualib/snax/gateserver.lua
+++ b/lualib/snax/gateserver.lua
@@ -101,17 +101,24 @@ function gateserver.start(handler)
end
function MSG.close(fd)
- if handler.disconnect then
- handler.disconnect(fd)
+ if fd ~= socket then
+ if handler.disconnect then
+ handler.disconnect(fd)
+ end
+ close_fd(fd)
end
- close_fd(fd)
end
function MSG.error(fd, msg)
- if handler.error then
- handler.error(fd, msg)
+ if fd == socket then
+ socketdriver.close(fd)
+ skynet.error(msg)
+ else
+ if handler.error then
+ handler.error(fd, msg)
+ end
+ close_fd(fd)
end
- close_fd(fd)
end
function MSG.warning(fd, size)
diff --git a/lualib/socket.lua b/lualib/socket.lua
index c5fe7858..7f1d603b 100644
--- a/lualib/socket.lua
+++ b/lualib/socket.lua
@@ -106,16 +106,17 @@ socket_message[4] = function(id, newid, addr)
end
-- SKYNET_SOCKET_TYPE_ERROR = 5
-socket_message[5] = function(id)
+socket_message[5] = function(id, _, err)
local s = socket_pool[id]
if s == nil then
- skynet.error("socket: error on unknown", id)
+ skynet.error("socket: error on unknown", id, err)
return
end
- if s.connected then
- skynet.error("socket: error on", id)
+ if s.connected or s.connecting then
+ skynet.error("socket: error on", id, err)
end
s.connected = false
+ driver.close(id)
wakeup(s)
end
@@ -170,6 +171,7 @@ local function connect(id, func)
id = id,
buffer = newbuffer,
connected = false,
+ connecting = true,
read_required = false,
co = false,
callback = func,
@@ -177,6 +179,7 @@ local function connect(id, func)
}
socket_pool[id] = s
suspend(s)
+ s.connecting = nil
if s.connected then
return id
else
@@ -221,7 +224,7 @@ function socket.close(id)
return
end
if s.connected then
- driver.close(s.id)
+ driver.close(id)
-- notice: call socket.close in __gc should be carefully,
-- because skynet.wait never return in __gc, so driver.clear may not be called
if s.co then
diff --git a/skynet-src/skynet_socket.c b/skynet-src/skynet_socket.c
index 9301419f..f6f8ec56 100644
--- a/skynet-src/skynet_socket.c
+++ b/skynet-src/skynet_socket.c
@@ -36,7 +36,11 @@ forward_message(int type, bool padding, struct socket_message * result) {
size_t sz = sizeof(*sm);
if (padding) {
if (result->data) {
- sz += strlen(result->data);
+ size_t msg_sz = strlen(result->data);
+ if (msg_sz > 128) {
+ msg_sz = 128;
+ }
+ sz += msg_sz;
} else {
result->data = "";
}
@@ -86,7 +90,7 @@ skynet_socket_poll() {
forward_message(SKYNET_SOCKET_TYPE_CONNECT, true, &result);
break;
case SOCKET_ERROR:
- forward_message(SKYNET_SOCKET_TYPE_ERROR, false, &result);
+ forward_message(SKYNET_SOCKET_TYPE_ERROR, true, &result);
break;
case SOCKET_ACCEPT:
forward_message(SKYNET_SOCKET_TYPE_ACCEPT, true, &result);
diff --git a/skynet-src/socket_server.c b/skynet-src/socket_server.c
index b2454d2e..7724a3c5 100644
--- a/skynet-src/socket_server.c
+++ b/skynet-src/socket_server.c
@@ -408,6 +408,7 @@ open_socket(struct socket_server *ss, struct request_open * request, struct sock
status = getaddrinfo( request->host, port, &ai_hints, &ai_list );
if ( status != 0 ) {
+ result->data = (void *)gai_strerror(status);
goto _failed;
}
int sock= -1;
@@ -428,12 +429,14 @@ open_socket(struct socket_server *ss, struct request_open * request, struct sock
}
if (sock < 0) {
+ result->data = strerror(errno);
goto _failed;
}
ns = new_fd(ss, id, sock, PROTOCOL_TCP, request->opaque, true);
if (ns == NULL) {
close(sock);
+ result->data = "reach skynet socket number limit";
goto _failed;
}
@@ -762,7 +765,7 @@ _failed:
result->opaque = request->opaque;
result->id = id;
result->ud = 0;
- result->data = NULL;
+ result->data = "reach skynet socket number limit";
ss->slot[HASH_ID(id)].type = SOCKET_TYPE_INVALID;
return SOCKET_ERROR;
@@ -803,7 +806,7 @@ bind_socket(struct socket_server *ss, struct request_bind *request, struct socke
result->ud = 0;
struct socket *s = new_fd(ss, id, request->fd, PROTOCOL_TCP, request->opaque, true);
if (s == NULL) {
- result->data = NULL;
+ result->data = "reach skynet socket number limit";
return SOCKET_ERROR;
}
sp_nonblocking(request->fd);
@@ -821,11 +824,13 @@ start_socket(struct socket_server *ss, struct request_start *request, struct soc
result->data = NULL;
struct socket *s = &ss->slot[HASH_ID(id)];
if (s->type == SOCKET_TYPE_INVALID || s->id !=id) {
+ result->data = "invalid socket";
return SOCKET_ERROR;
}
if (s->type == SOCKET_TYPE_PACCEPT || s->type == SOCKET_TYPE_PLISTEN) {
if (sp_add(ss->event_fd, s->fd, s)) {
s->type = SOCKET_TYPE_INVALID;
+ result->data = strerror(errno);
return SOCKET_ERROR;
}
s->type = (s->type == SOCKET_TYPE_PACCEPT) ? SOCKET_TYPE_CONNECTED : SOCKET_TYPE_LISTEN;
@@ -913,7 +918,7 @@ set_udp_address(struct socket_server *ss, struct request_setudp *request, struct
result->opaque = s->opaque;
result->id = s->id;
result->ud = 0;
- result->data = NULL;
+ result->data = "protocol mismatch";
return SOCKET_ERROR;
}
@@ -995,6 +1000,7 @@ forward_message_tcp(struct socket_server *ss, struct socket *s, struct socket_me
default:
// close when error
force_close(ss, s, result);
+ result->data = strerror(errno);
return SOCKET_ERROR;
}
return -1;
@@ -1055,6 +1061,7 @@ forward_message_udp(struct socket_server *ss, struct socket *s, struct socket_me
default:
// close when error
force_close(ss, s, result);
+ result->data = strerror(errno);
return SOCKET_ERROR;
}
return -1;
@@ -1088,6 +1095,7 @@ report_connect(struct socket_server *ss, struct socket *s, struct socket_message
int code = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &error, &len);
if (code < 0 || error) {
force_close(ss,s, result);
+ result->data = strerror(errno);
return SOCKET_ERROR;
} else {
s->type = SOCKET_TYPE_CONNECTED;
@@ -1111,14 +1119,22 @@ report_connect(struct socket_server *ss, struct socket *s, struct socket_message
}
}
-// return 0 when failed
+// return 0 when failed, or -1 when file limit
static int
report_accept(struct socket_server *ss, struct socket *s, struct socket_message *result) {
union sockaddr_all u;
socklen_t len = sizeof(u);
int client_fd = accept(s->fd, &u.s, &len);
if (client_fd < 0) {
- return 0;
+ if (errno == EMFILE || errno == ENFILE) {
+ result->opaque = s->opaque;
+ result->id = s->id;
+ result->ud = 0;
+ result->data = strerror(errno);
+ return -1;
+ } else {
+ return 0;
+ }
}
int id = reserve_id(ss);
if (id < 0) {
@@ -1203,11 +1219,16 @@ socket_server_poll(struct socket_server *ss, struct socket_message * result, int
switch (s->type) {
case SOCKET_TYPE_CONNECTING:
return report_connect(ss, s, result);
- case SOCKET_TYPE_LISTEN:
- if (report_accept(ss, s, result)) {
+ case SOCKET_TYPE_LISTEN: {
+ int ok = report_accept(ss, s, result);
+ if (ok > 0) {
return SOCKET_ACCEPT;
- }
+ } if (ok < 0 ) {
+ return SOCKET_ERROR;
+ }
+ // when ok == 0, retry
break;
+ }
case SOCKET_TYPE_INVALID:
fprintf(stderr, "socket-server: invalid socket\n");
break;
From 00dbf6e9969e7f6ea498cffd3740d991847db710 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Fri, 18 Sep 2015 14:10:12 +0800
Subject: [PATCH 55/97] DH key exchange can't be 0 , avoid attack
---
lualib-src/lua-crypt.c | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/lualib-src/lua-crypt.c b/lualib-src/lua-crypt.c
index 0284c48b..2cb11f40 100644
--- a/lualib-src/lua-crypt.c
+++ b/lualib-src/lua-crypt.c
@@ -338,8 +338,13 @@ static int
lrandomkey(lua_State *L) {
char tmp[8];
int i;
+ char x = 0;
for (i=0;i<8;i++) {
tmp[i] = random() & 0xff;
+ x ^= tmp[i];
+ }
+ if (x==0) {
+ tmp[0] |= 1; // avoid 0
}
lua_pushlstring(L, tmp, 8);
return 1;
@@ -718,8 +723,13 @@ static int
ldhsecret(lua_State *L) {
uint32_t x[2], y[2];
read64(L, x, y);
- uint64_t r = powmodp((uint64_t)x[0] | (uint64_t)x[1]<<32,
- (uint64_t)y[0] | (uint64_t)y[1]<<32);
+ uint64_t xx = (uint64_t)x[0] | (uint64_t)x[1]<<32;
+ uint64_t yy = (uint64_t)y[0] | (uint64_t)y[1]<<32;
+ if (xx == 0)
+ xx = 1;
+ if (yy == 0)
+ yy = 1;
+ uint64_t r = powmodp(xx, yy);
push64(L, r);
@@ -739,7 +749,11 @@ ldhexchange(lua_State *L) {
xx[0] = x[0] | x[1]<<8 | x[2]<<16 | x[3]<<24;
xx[1] = x[4] | x[5]<<8 | x[6]<<16 | x[7]<<24;
- uint64_t r = powmodp(5, (uint64_t)xx[0] | (uint64_t)xx[1]<<32);
+ uint64_t x64 = (uint64_t)xx[0] | (uint64_t)xx[1]<<32;
+ if (x64 == 0)
+ x64 = 1;
+
+ uint64_t r = powmodp(5, x64);
push64(L, r);
return 1;
}
From 008351573a518ab92aea5431363e9d45414ec26a Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Fri, 18 Sep 2015 14:13:16 +0800
Subject: [PATCH 56/97] raise error when DH param is 0
---
lualib-src/lua-crypt.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/lualib-src/lua-crypt.c b/lualib-src/lua-crypt.c
index 2cb11f40..405679a9 100644
--- a/lualib-src/lua-crypt.c
+++ b/lualib-src/lua-crypt.c
@@ -725,10 +725,8 @@ ldhsecret(lua_State *L) {
read64(L, x, y);
uint64_t xx = (uint64_t)x[0] | (uint64_t)x[1]<<32;
uint64_t yy = (uint64_t)y[0] | (uint64_t)y[1]<<32;
- if (xx == 0)
- xx = 1;
- if (yy == 0)
- yy = 1;
+ if (xx == 0 || yy == 0)
+ return luaL_error(L, "Can't be 0");
uint64_t r = powmodp(xx, yy);
push64(L, r);
@@ -751,7 +749,7 @@ ldhexchange(lua_State *L) {
uint64_t x64 = (uint64_t)xx[0] | (uint64_t)xx[1]<<32;
if (x64 == 0)
- x64 = 1;
+ return luaL_error(L, "Can't be 0");
uint64_t r = powmodp(5, x64);
push64(L, r);
From 752a501f681a4a692971a49ebd2d4cc389ddbd75 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Mon, 21 Sep 2015 10:40:09 +0800
Subject: [PATCH 57/97] bugfix: remove DONTCOPY tag from type
---
service-src/service_harbor.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/service-src/service_harbor.c b/service-src/service_harbor.c
index ed05190b..70abe82b 100644
--- a/service-src/service_harbor.c
+++ b/service-src/service_harbor.c
@@ -313,10 +313,10 @@ forward_local_messsage(struct harbor *h, void *msg, int sz) {
message_to_header((const uint32_t *)cookie, &header);
uint32_t destination = header.destination;
- int type = (destination >> HANDLE_REMOTE_SHIFT) | PTYPE_TAG_DONTCOPY;
+ int type = destination >> HANDLE_REMOTE_SHIFT;
destination = (destination & HANDLE_MASK) | ((uint32_t)h->id << HANDLE_REMOTE_SHIFT);
- if (skynet_send(h->ctx, header.source, destination, type, (int)header.session, (void *)msg, sz-HEADER_COOKIE_LENGTH) < 0) {
+ if (skynet_send(h->ctx, header.source, destination, type | PTYPE_TAG_DONTCOPY , (int)header.session, (void *)msg, sz-HEADER_COOKIE_LENGTH) < 0) {
if (type != PTYPE_ERROR) {
// don't need report error when type is error
skynet_send(h->ctx, destination, header.source , PTYPE_ERROR, (int)header.session, NULL, 0);
From 325452a242657ac0c87a71a19e625d8ba16bd3b3 Mon Sep 17 00:00:00 2001
From: bingo
Date: Mon, 21 Sep 2015 11:21:36 +0800
Subject: [PATCH 58/97] Signed-off-by: bingo
---
lualib/snax/gateserver.lua | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lualib/snax/gateserver.lua b/lualib/snax/gateserver.lua
index 68f77b58..bf62e2ce 100644
--- a/lualib/snax/gateserver.lua
+++ b/lualib/snax/gateserver.lua
@@ -48,7 +48,6 @@ function gateserver.start(handler)
function CMD.close()
assert(socket)
socketdriver.close(socket)
- socket = nil
end
local MSG = {}
@@ -106,6 +105,8 @@ function gateserver.start(handler)
handler.disconnect(fd)
end
close_fd(fd)
+ else
+ socket = nil
end
end
From 63942496fdfa7c3b98364e86fab067165da4e270 Mon Sep 17 00:00:00 2001
From: great90 <897346026@qq.com>
Date: Mon, 21 Sep 2015 23:50:18 +0800
Subject: [PATCH 59/97] =?UTF-8?q?=E4=BB=8Echeck=5Fwsz=E5=8F=91=E9=80=81?=
=?UTF-8?q?=E7=9A=84SKYNET=5FSOCKET=5FTYPE=5FWARNING=E6=B6=88=E6=81=AF?=
=?UTF-8?q?=E4=BC=9Aassert=E5=A4=B1=E8=B4=A5=EF=BC=8C=E5=AF=BC=E8=87=B4cor?=
=?UTF-8?q?edump?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
service-src/service_gate.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/service-src/service_gate.c b/service-src/service_gate.c
index ec44c722..d59b4050 100644
--- a/service-src/service_gate.c
+++ b/service-src/service_gate.c
@@ -295,7 +295,6 @@ _cb(struct skynet_context * ctx, void * ud, int type, int session, uint32_t sour
}
}
case PTYPE_SOCKET:
- assert(source == 0);
// recv socket message from skynet_socket
dispatch_socket_message(g, msg, (int)(sz-sizeof(struct skynet_socket_message)));
break;
From cb9feb34bd263d3c0390c2ca2c55c887026ba945 Mon Sep 17 00:00:00 2001
From: zhengfangxin
Date: Sat, 26 Sep 2015 21:03:38 +0800
Subject: [PATCH 60/97] 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 61/97] 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 62/97] 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.
-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
-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 63/97] 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 64/97] 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 65/97] 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 66/97] 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 67/97] 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 68/97] 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 69/97] 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 70/97] 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 71/97] 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 72/97] 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 73/97] 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 74/97] 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 75/97] 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 76/97] 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 77/97] 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) {
From fe3954fb041c676557acccf9c5148c20d4a771ba Mon Sep 17 00:00:00 2001
From: fztcjjl
Date: Sat, 24 Oct 2015 01:35:16 +0800
Subject: [PATCH 78/97] add a callback for mysql auth
---
lualib/mysql.lua | 13 ++++++++-----
test/testmysql.lua | 6 ++----
2 files changed, 10 insertions(+), 9 deletions(-)
mode change 100755 => 100644 lualib/mysql.lua
diff --git a/lualib/mysql.lua b/lualib/mysql.lua
old mode 100755
new mode 100644
index 305e900b..331c7942
--- a/lualib/mysql.lua
+++ b/lualib/mysql.lua
@@ -418,7 +418,7 @@ local function _recv_auth_resp(self)
end
-local function _mysql_login(self,user,password,database)
+local function _mysql_login(self,user,password,database,cb)
return function(sockchannel)
local packet, typ, err = sockchannel:response( _recv_decode_packet_resp(self) )
@@ -490,7 +490,10 @@ local function _mysql_login(self,user,password,database)
local packet_len = #req
local authpacket=_compose_packet(self,req,packet_len)
- return sockchannel:request(authpacket,_recv_auth_resp(self))
+ sockchannel:request(authpacket,_recv_auth_resp(self))
+ if cb then
+ cb(self)
+ end
end
end
@@ -626,7 +629,7 @@ local function _query_resp(self)
end
end
-function _M.connect( opts)
+function _M.connect(opts, cb)
local self = setmetatable( {}, mt)
@@ -645,11 +648,11 @@ function _M.connect( opts)
local channel = socketchannel.channel {
host = opts.host,
port = opts.port or 3306,
- auth = _mysql_login(self,user,password,database ),
+ auth = _mysql_login(self,user,password,database,cb),
}
+ self.sockchannel = channel
-- try connect first only once
channel:connect(true)
- self.sockchannel = channel
return self
diff --git a/test/testmysql.lua b/test/testmysql.lua
index 7bd54855..8679e7bc 100644
--- a/test/testmysql.lua
+++ b/test/testmysql.lua
@@ -70,21 +70,19 @@ local function test3( db)
end
skynet.start(function()
- local db=mysql.connect{
+ local db=mysql.connect({
host="127.0.0.1",
port=3306,
database="skynet",
user="root",
password="1",
max_packet_size = 1024 * 1024
- }
+ }, function(db) db:query("set charset utf8") end)
if not db then
print("failed to connect")
end
print("testmysql success to connect to mysql server")
- db:query("set names utf8")
-
local res = db:query("drop table if exists cats")
res = db:query("create table cats "
.."(id serial primary key, ".. "name varchar(5))")
From 1653b3213a8faae7df79438f4c79e4c2157b3352 Mon Sep 17 00:00:00 2001
From: fztcjjl
Date: Sat, 24 Oct 2015 06:37:25 +0800
Subject: [PATCH 79/97] add a callback for mysql auth
---
lualib/mysql.lua | 10 +++++-----
test/testmysql.lua | 8 ++++++--
2 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/lualib/mysql.lua b/lualib/mysql.lua
index 331c7942..c3573ae2 100644
--- a/lualib/mysql.lua
+++ b/lualib/mysql.lua
@@ -418,7 +418,7 @@ local function _recv_auth_resp(self)
end
-local function _mysql_login(self,user,password,database,cb)
+local function _mysql_login(self,user,password,database,on_connect)
return function(sockchannel)
local packet, typ, err = sockchannel:response( _recv_decode_packet_resp(self) )
@@ -491,8 +491,8 @@ local function _mysql_login(self,user,password,database,cb)
local authpacket=_compose_packet(self,req,packet_len)
sockchannel:request(authpacket,_recv_auth_resp(self))
- if cb then
- cb(self)
+ if on_connect then
+ on_connect(self)
end
end
end
@@ -629,7 +629,7 @@ local function _query_resp(self)
end
end
-function _M.connect(opts, cb)
+function _M.connect(opts)
local self = setmetatable( {}, mt)
@@ -648,7 +648,7 @@ function _M.connect(opts, cb)
local channel = socketchannel.channel {
host = opts.host,
port = opts.port or 3306,
- auth = _mysql_login(self,user,password,database,cb),
+ auth = _mysql_login(self,user,password,database,opts.on_connect),
}
self.sockchannel = channel
-- try connect first only once
diff --git a/test/testmysql.lua b/test/testmysql.lua
index 8679e7bc..e8b420aa 100644
--- a/test/testmysql.lua
+++ b/test/testmysql.lua
@@ -70,14 +70,18 @@ local function test3( db)
end
skynet.start(function()
+ local function on_connect(db)
+ db:query("set charset utf8");
+ end
local db=mysql.connect({
host="127.0.0.1",
port=3306,
database="skynet",
user="root",
password="1",
- max_packet_size = 1024 * 1024
- }, function(db) db:query("set charset utf8") end)
+ max_packet_size = 1024 * 1024,
+ on_connect = on_connect
+ })
if not db then
print("failed to connect")
end
From f5740e00b17d125e0be02510a93b7db6aea59b5a Mon Sep 17 00:00:00 2001
From: nbwk1988
Date: Mon, 26 Oct 2015 16:12:10 +0800
Subject: [PATCH 80/97] add hmac_md5
add hmac_md5
---
lualib/md5.lua | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/lualib/md5.lua b/lualib/md5.lua
index 26f5cfa6..ceaddb38 100644
--- a/lualib/md5.lua
+++ b/lualib/md5.lua
@@ -15,4 +15,22 @@ function core.sumhexa (k)
end))
end
-return core
\ No newline at end of file
+function core.hmac_md5(data,key)
+ if #key>64 then
+ key=core.sum(key)
+ key=string.sub(key,1,16)
+ end
+
+ local b=table.pack(string.byte(key,1,#key))
+ local ipad_s=""
+ local opad_s=""
+ for i=1,64 do
+ ipad_s=ipad_s..string.char((b[i] or 0)~0x36)
+ opad_s=opad_s..string.char((b[i] or 0)~0x5c)
+ end
+ local istr=core.sum(ipad_s..data)
+ local ostr=core.sumhexa(opad_s..istr)
+ return ostr
+end
+
+return core
From 1999a03ff7f913fe97eb58c3a7c5baa17f73da49 Mon Sep 17 00:00:00 2001
From: nbwk1988
Date: Tue, 27 Oct 2015 10:44:23 +0800
Subject: [PATCH 81/97] =?UTF-8?q?=E4=BC=98=E5=8C=96hmac?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
lualib/md5.lua | 22 ++++++++++++----------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/lualib/md5.lua b/lualib/md5.lua
index ceaddb38..90e28739 100644
--- a/lualib/md5.lua
+++ b/lualib/md5.lua
@@ -15,19 +15,21 @@ function core.sumhexa (k)
end))
end
-function core.hmac_md5(data,key)
+local function get_ipad(c)
+ return string.char(c:byte() ~ 0x36)
+end
+
+local function get_opad(c)
+ return string.char(c:byte() ~ 0x5c)
+end
+
+function core.hmacmd5(data,key)
if #key>64 then
key=core.sum(key)
- key=string.sub(key,1,16)
- end
-
- local b=table.pack(string.byte(key,1,#key))
- local ipad_s=""
- local opad_s=""
- for i=1,64 do
- ipad_s=ipad_s..string.char((b[i] or 0)~0x36)
- opad_s=opad_s..string.char((b[i] or 0)~0x5c)
+ key=key:sub(1,16)
end
+ local ipad_s=key:gsub(".", get_ipad)..string.rep("6",64-#key)
+ local opad_s=key:gsub(".", get_opad)..string.rep("\\",64-#key)
local istr=core.sum(ipad_s..data)
local ostr=core.sumhexa(opad_s..istr)
return ostr
From a4af35f442ca4779d1320a6dd4a38eba5a7e4e33 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Tue, 27 Oct 2015 14:00:25 +0800
Subject: [PATCH 82/97] fix issue #364
---
lualib/snax/interface.lua | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/lualib/snax/interface.lua b/lualib/snax/interface.lua
index bd996c4d..740f09d9 100644
--- a/lualib/snax/interface.lua
+++ b/lualib/snax/interface.lua
@@ -59,8 +59,6 @@ return function (name , G, loader)
end
end
- setmetatable(G, { __index = env , __newindex = init_system })
-
local pattern
do
@@ -85,9 +83,10 @@ return function (name , G, loader)
end
end
- mainfunc()
-
+ setmetatable(G, { __index = env , __newindex = init_system })
+ local ok, err = pcall(mainfunc)
setmetatable(G, nil)
+ assert(ok,err)
for k,v in pairs(temp_global) do
G[k] = v
From 13d920e1852d71584c830dd3b76fc99810699a03 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Tue, 27 Oct 2015 15:40:15 +0800
Subject: [PATCH 83/97] body may contain ascii 0, see issue #365
---
lualib/http/httpc.lua | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lualib/http/httpc.lua b/lualib/http/httpc.lua
index ae771dc8..49ccb9b8 100644
--- a/lualib/http/httpc.lua
+++ b/lualib/http/httpc.lua
@@ -22,8 +22,9 @@ local function request(fd, method, host, url, recvheader, header, content)
end
if content then
- local data = string.format("%s %s HTTP/1.1\r\n%scontent-length:%d\r\n\r\n%s", method, url, header_content, #content, content)
+ local data = string.format("%s %s HTTP/1.1\r\n%scontent-length:%d\r\n\r\n", method, url, header_content, #content)
write(data)
+ write(content)
else
local request_header = string.format("%s %s HTTP/1.1\r\n%scontent-length:0\r\n\r\n", method, url, header_content)
write(request_header)
From 935863f43455c5e902d1c62a7e9d481b3eda2cb1 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Wed, 28 Oct 2015 16:12:01 +0800
Subject: [PATCH 84/97] report connect failed reason
---
lualib/socket.lua | 6 +++++-
lualib/socketchannel.lua | 18 +++++++++++-------
skynet-src/socket_server.c | 5 ++++-
3 files changed, 20 insertions(+), 9 deletions(-)
diff --git a/lualib/socket.lua b/lualib/socket.lua
index 58fe2678..25a6099f 100644
--- a/lualib/socket.lua
+++ b/lualib/socket.lua
@@ -112,8 +112,10 @@ socket_message[5] = function(id, _, err)
skynet.error("socket: error on unknown", id, err)
return
end
- if s.connected or s.connecting then
+ if s.connected then
skynet.error("socket: error on", id, err)
+ elseif s.connecting then
+ s.connecting = err
end
s.connected = false
driver.close(id)
@@ -179,11 +181,13 @@ local function connect(id, func)
}
socket_pool[id] = s
suspend(s)
+ local err = s.connecting
s.connecting = nil
if s.connected then
return id
else
socket_pool[id] = nil
+ return nil, err
end
end
diff --git a/lualib/socketchannel.lua b/lualib/socketchannel.lua
index 7e7a0f6b..31a339c5 100644
--- a/lualib/socketchannel.lua
+++ b/lualib/socketchannel.lua
@@ -209,11 +209,11 @@ local function connect_once(self)
return false
end
assert(not self.__sock and not self.__authcoroutine)
- local fd = socket.open(self.__host, self.__port)
+ local fd,err = socket.open(self.__host, self.__port)
if not fd then
fd = connect_backup(self)
if not fd then
- return false
+ return false, err
end
end
if self.__nodelay then
@@ -247,13 +247,16 @@ end
local function try_connect(self , once)
local t = 0
while not self.__closed do
- if connect_once(self) then
+ local ok, err = connect_once(self)
+ if ok then
if not once then
skynet.error("socket: connect to", self.__host, self.__port)
end
- return true
+ return
elseif once then
- return false
+ return err
+ else
+ skynet.error("socket: connect", err)
end
if t > 1000 then
skynet.error("socket: try to reconnect", self.__host, self.__port)
@@ -287,6 +290,7 @@ local function block_connect(self, once)
if r ~= nil then
return r
end
+ local err
if #self.__connecting > 0 then
-- connecting in other coroutine
@@ -295,7 +299,7 @@ local function block_connect(self, once)
skynet.wait(co)
else
self.__connecting[1] = true
- try_connect(self, once)
+ err = try_connect(self, once)
self.__connecting[1] = nil
for i=2, #self.__connecting do
local co = self.__connecting[i]
@@ -306,7 +310,7 @@ local function block_connect(self, once)
r = check_connection(self)
if r == nil then
- error(string.format("Connect to %s:%d failed", self.__host, self.__port))
+ error(string.format("Connect to %s:%d failed (%s)", self.__host, self.__port, err))
else
return r
end
diff --git a/skynet-src/socket_server.c b/skynet-src/socket_server.c
index 4963dd37..6ee4d03a 100644
--- a/skynet-src/socket_server.c
+++ b/skynet-src/socket_server.c
@@ -1095,7 +1095,10 @@ report_connect(struct socket_server *ss, struct socket *s, struct socket_message
int code = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &error, &len);
if (code < 0 || error) {
force_close(ss,s, result);
- result->data = strerror(errno);
+ if (code >= 0)
+ result->data = strerror(error);
+ else
+ result->data = strerror(errno);
return SOCKET_ERROR;
} else {
s->type = SOCKET_TYPE_CONNECTED;
From 0199ba1382c1007e9ba9e4f79d9f1b916910abb2 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Wed, 28 Oct 2015 17:37:06 +0800
Subject: [PATCH 85/97] sharedata support filename string
---
lualib/skynet.lua | 8 ++++++--
service/sharedatad.lua | 14 ++++++++++++--
2 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/lualib/skynet.lua b/lualib/skynet.lua
index c20efaa2..2dd38f8d 100644
--- a/lualib/skynet.lua
+++ b/lualib/skynet.lua
@@ -608,11 +608,15 @@ local function init_all()
end
end
+local function ret(f, ...)
+ f()
+ return ...
+end
+
local function init_template(start)
init_all()
init_func = {}
- start()
- init_all()
+ return ret(init_all, start())
end
function skynet.pcall(start)
diff --git a/service/sharedatad.lua b/service/sharedatad.lua
index d76fd115..1ae9022c 100644
--- a/service/sharedatad.lua
+++ b/service/sharedatad.lua
@@ -1,6 +1,8 @@
local skynet = require "skynet"
local sharedata = require "sharedata.corelib"
local table = table
+local cache = require "skynet.codecache"
+cache.mode "OFF" -- turn off codecache, because CMD.new may load data file
local NORET = {}
local pool = {}
@@ -43,9 +45,17 @@ function CMD.new(name, t)
value = t
elseif dt == "string" then
value = setmetatable({}, env_mt)
- local f = load(t, "=" .. name, "t", value)
- assert(skynet.pcall(f))
+ local f
+ if t:sub(1,1) == "@" then
+ f = assert(loadfile(t:sub(2),"bt",value))
+ else
+ f = assert(load(t, "=" .. name, "bt", value))
+ end
+ local _, ret = assert(skynet.pcall(f))
setmetatable(value, nil)
+ if type(ret) == "table" then
+ value = ret
+ end
elseif dt == "nil" then
value = {}
else
From ac4d51b779c3719d6f8723137e343228291d9232 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Thu, 29 Oct 2015 11:22:26 +0800
Subject: [PATCH 86/97] bugfix issue #368
---
lualib-src/sproto/sproto.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lualib-src/sproto/sproto.c b/lualib-src/sproto/sproto.c
index ec77441b..68ccd047 100644
--- a/lualib-src/sproto/sproto.c
+++ b/lualib-src/sproto/sproto.c
@@ -677,12 +677,12 @@ 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) {
--sz; // the length of null string is 1
}
+ assert(sz <= size-SIZEOF_LENGTH); // verify buffer overflow
return fill_size(data, sz);
}
From d1b26a60eb016fac567d1422638fa6dbae5f60ec Mon Sep 17 00:00:00 2001
From: kexiao8
Date: Sat, 31 Oct 2015 17:43:33 +0800
Subject: [PATCH 87/97] =?UTF-8?q?=20repeated=20=E2=80=9Cstruct=20table"=20?=
=?UTF-8?q?of=20line=2019?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
lualib-src/lua-sharedata.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/lualib-src/lua-sharedata.c b/lualib-src/lua-sharedata.c
index 99cadd15..abbc175d 100644
--- a/lualib-src/lua-sharedata.c
+++ b/lualib-src/lua-sharedata.c
@@ -36,8 +36,6 @@ struct node {
uint8_t nocolliding; // 0 means colliding slot
};
-struct table;
-
struct state {
int dirty;
int ref;
From d83fc0c00fe5db22c8e47f3d896ea375a224cba9 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Mon, 2 Nov 2015 19:50:51 +0800
Subject: [PATCH 88/97] sproto support all integer representation
---
lualib-src/sproto/lsproto.c | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/lualib-src/sproto/lsproto.c b/lualib-src/sproto/lsproto.c
index 16eaa022..1d71d887 100644
--- a/lualib-src/sproto/lsproto.c
+++ b/lualib-src/sproto/lsproto.c
@@ -41,8 +41,18 @@ LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
#if LUA_VERSION_NUM < 503
-// lua_isinteger is lua 5.3 api
-#define lua_isinteger lua_isnumber
+#if LUA_VERSION_NUM < 502
+static lua_Integer lua_tointegerx(lua_State *L, int idx, int *isnum) {
+ if (lua_isnumber(L, idx)) {
+ if (isnum) *isnum = 1;
+ return lua_tointeger(L, idx);
+ }
+ else {
+ if (isnum) *isnum = 0;
+ return 0;
+ }
+}
+#endif
// work around , use push & lua_gettable may be better
#define lua_geti lua_rawgeti
@@ -156,11 +166,11 @@ encode(const struct sproto_arg *args) {
case SPROTO_TINTEGER: {
lua_Integer v;
lua_Integer vh;
- if (!lua_isinteger(L, -1)) {
+ int isnum;
+ v = lua_tointegerx(L, -1, &isnum);
+ if(!isnum) {
return luaL_error(L, ".%s[%d] is not an integer (Is a %s)",
args->tagname, args->index, lua_typename(L, lua_type(L, -1)));
- } else {
- v = lua_tointeger(L, -1);
}
lua_pop(L,1);
// notice: in lua 5.2, lua_Integer maybe 52bit
From 9382454bcdd1443db501136089e6ce0056392ab3 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Tue, 10 Nov 2015 12:12:42 +0800
Subject: [PATCH 89/97] update jemalloc to 4.0.4
---
3rd/jemalloc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/3rd/jemalloc b/3rd/jemalloc
index e9192eac..91010a9e 160000
--- a/3rd/jemalloc
+++ b/3rd/jemalloc
@@ -1 +1 @@
-Subproject commit e9192eacf8935e29fc62fddc2701f7942b1cc02c
+Subproject commit 91010a9e2ebfc84b1ac1ed7fdde3bfed4f65f180
From c28ae25c7020673790c160d30ef7488613aeb458 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Tue, 10 Nov 2015 12:19:04 +0800
Subject: [PATCH 90/97] release 1.0.0 beta
---
HISTORY.md | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/HISTORY.md b/HISTORY.md
index 48c7a069..23e1ae10 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -1,3 +1,22 @@
+v1.0.0-beta (2015-11-10)
+-----------
+* Improve and fix bug for sproto
+* Add global short string pool for lua vm
+* Add code cache mode
+* Add a callback for mysql auth
+* Add hmac_md5
+* Sharedata support filename as a string
+* Fix a bug in socket.httpc
+* Fix a lua stack overflow bug in lua bson
+* Fix a socketchannel bug may block the data steam
+* Avoid dead loop when sending message to the service exiting
+* Fix memory leak in netpack
+* Improve DH key exchange implement
+* Minor fix for socket
+* Minor fix for multicast
+* Update jemalloc to 4.0.4
+* Update lpeg to 1.0.0
+
v1.0.0-alpha10 (2015-8-17)
-----------
* Remove the size limit of cluster RPC message.
From 7521fe05300c117923a57c5cbd6409de355b1f5a Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Wed, 11 Nov 2015 10:44:50 +0800
Subject: [PATCH 91/97] socket.shutdown abandon unsend buffer now, see issue
#371
---
lualib-src/lua-socket.c | 9 +++++++++
lualib/socket.lua | 14 +++++++++-----
skynet-src/skynet_socket.c | 6 ++++++
skynet-src/skynet_socket.h | 1 +
skynet-src/socket_server.c | 14 +++++++++++++-
skynet-src/socket_server.h | 1 +
6 files changed, 39 insertions(+), 6 deletions(-)
diff --git a/lualib-src/lua-socket.c b/lualib-src/lua-socket.c
index 5ac0b359..9d12ab52 100644
--- a/lualib-src/lua-socket.c
+++ b/lualib-src/lua-socket.c
@@ -461,6 +461,14 @@ lclose(lua_State *L) {
return 0;
}
+static int
+lshutdown(lua_State *L) {
+ int id = luaL_checkinteger(L,1);
+ struct skynet_context * ctx = lua_touserdata(L, lua_upvalueindex(1));
+ skynet_socket_shutdown(ctx, id);
+ return 0;
+}
+
static int
llisten(lua_State *L) {
const char * host = luaL_checkstring(L,1);
@@ -639,6 +647,7 @@ luaopen_socketdriver(lua_State *L) {
luaL_Reg l2[] = {
{ "connect", lconnect },
{ "close", lclose },
+ { "shutdown", lshutdown },
{ "listen", llisten },
{ "send", lsend },
{ "lsend", lsendlow },
diff --git a/lualib/socket.lua b/lualib/socket.lua
index 25a6099f..1fd9d60b 100644
--- a/lualib/socket.lua
+++ b/lualib/socket.lua
@@ -118,7 +118,7 @@ socket_message[5] = function(id, _, err)
s.connecting = err
end
s.connected = false
- driver.close(id)
+ driver.shutdown(id)
wakeup(s)
end
@@ -210,18 +210,22 @@ function socket.start(id, func)
return connect(id, func)
end
-function socket.shutdown(id)
+local function close_fd(id, func)
local s = socket_pool[id]
if s then
if s.buffer then
driver.clear(s.buffer,buffer_pool)
end
if s.connected then
- driver.close(id)
+ func(id)
end
end
end
+function socket.shutdown(id)
+ close_fd(id, driver.shutdown)
+end
+
function socket.close(id)
local s = socket_pool[id]
if s == nil then
@@ -232,7 +236,7 @@ function socket.close(id)
-- notice: call socket.close in __gc should be carefully,
-- because skynet.wait never return in __gc, so driver.clear may not be called
if s.co then
- -- reading this socket on another coroutine, so don't shutdown (clear the buffer) immediatel
+ -- reading this socket on another coroutine, so don't shutdown (clear the buffer) immediately
-- wait reading coroutine read the buffer.
assert(not s.closing)
s.closing = coroutine.running()
@@ -242,7 +246,7 @@ function socket.close(id)
end
s.connected = false
end
- socket.shutdown(id)
+ close_fd(id) -- clear the buffer (already close fd)
assert(s.lock_set == nil or next(s.lock_set) == nil)
socket_pool[id] = nil
end
diff --git a/skynet-src/skynet_socket.c b/skynet-src/skynet_socket.c
index f6f8ec56..2f3aec84 100644
--- a/skynet-src/skynet_socket.c
+++ b/skynet-src/skynet_socket.c
@@ -159,6 +159,12 @@ skynet_socket_close(struct skynet_context *ctx, int id) {
socket_server_close(SOCKET_SERVER, source, id);
}
+void
+skynet_socket_shutdown(struct skynet_context *ctx, int id) {
+ uint32_t source = skynet_context_handle(ctx);
+ socket_server_shutdown(SOCKET_SERVER, source, id);
+}
+
void
skynet_socket_start(struct skynet_context *ctx, int id) {
uint32_t source = skynet_context_handle(ctx);
diff --git a/skynet-src/skynet_socket.h b/skynet-src/skynet_socket.h
index bcdc137c..55b98595 100644
--- a/skynet-src/skynet_socket.h
+++ b/skynet-src/skynet_socket.h
@@ -29,6 +29,7 @@ int skynet_socket_listen(struct skynet_context *ctx, const char *host, int port,
int skynet_socket_connect(struct skynet_context *ctx, const char *host, int port);
int skynet_socket_bind(struct skynet_context *ctx, int fd);
void skynet_socket_close(struct skynet_context *ctx, int id);
+void skynet_socket_shutdown(struct skynet_context *ctx, int id);
void skynet_socket_start(struct skynet_context *ctx, int id);
void skynet_socket_nodelay(struct skynet_context *ctx, int id);
diff --git a/skynet-src/socket_server.c b/skynet-src/socket_server.c
index 6ee4d03a..2e26e24f 100644
--- a/skynet-src/socket_server.c
+++ b/skynet-src/socket_server.c
@@ -119,6 +119,7 @@ struct request_setudp {
struct request_close {
int id;
+ int shutdown;
uintptr_t opaque;
};
@@ -787,7 +788,7 @@ close_socket(struct socket_server *ss, struct request_close *request, struct soc
if (type != -1)
return type;
}
- if (send_buffer_empty(s)) {
+ if (request->shutdown || send_buffer_empty(s)) {
force_close(ss,s,result);
result->id = id;
result->opaque = request->opaque;
@@ -1366,6 +1367,17 @@ void
socket_server_close(struct socket_server *ss, uintptr_t opaque, int id) {
struct request_package request;
request.u.close.id = id;
+ request.u.close.shutdown = 0;
+ request.u.close.opaque = opaque;
+ send_request(ss, &request, 'K', sizeof(request.u.close));
+}
+
+
+void
+socket_server_shutdown(struct socket_server *ss, uintptr_t opaque, int id) {
+ struct request_package request;
+ request.u.close.id = id;
+ request.u.close.shutdown = 1;
request.u.close.opaque = opaque;
send_request(ss, &request, 'K', sizeof(request.u.close));
}
diff --git a/skynet-src/socket_server.h b/skynet-src/socket_server.h
index b6f0f5fb..41ef9cca 100644
--- a/skynet-src/socket_server.h
+++ b/skynet-src/socket_server.h
@@ -26,6 +26,7 @@ int socket_server_poll(struct socket_server *, struct socket_message *result, in
void socket_server_exit(struct socket_server *);
void socket_server_close(struct socket_server *, uintptr_t opaque, int id);
+void socket_server_shutdown(struct socket_server *, uintptr_t opaque, int id);
void socket_server_start(struct socket_server *, uintptr_t opaque, int id);
// return -1 when error
From 9f3baf2ee3e0157d2f3f37ffdafdce502a17f4ad Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Wed, 11 Nov 2015 15:06:10 +0800
Subject: [PATCH 92/97] fix issue #372
---
skynet-src/skynet_error.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/skynet-src/skynet_error.c b/skynet-src/skynet_error.c
index 962ea597..856c4700 100644
--- a/skynet-src/skynet_error.c
+++ b/skynet-src/skynet_error.c
@@ -28,7 +28,7 @@ skynet_error(struct skynet_context * context, const char *msg, ...) {
va_start(ap,msg);
int len = vsnprintf(tmp, LOG_MESSAGE_SIZE, msg, ap);
va_end(ap);
- if (len < LOG_MESSAGE_SIZE) {
+ if (len >=0 && len < LOG_MESSAGE_SIZE) {
data = skynet_strdup(tmp);
} else {
int max_size = LOG_MESSAGE_SIZE;
@@ -44,6 +44,11 @@ skynet_error(struct skynet_context * context, const char *msg, ...) {
skynet_free(data);
}
}
+ if (len < 0) {
+ skynet_free(data);
+ perror("vsnprintf error :");
+ return;
+ }
struct skynet_message smsg;
From fa729d593b2672776ff0e614561a315a44bf0ea2 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Thu, 12 Nov 2015 10:53:14 +0800
Subject: [PATCH 93/97] lua alloc use raw allocator
---
skynet-src/malloc_hook.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/skynet-src/malloc_hook.c b/skynet-src/malloc_hook.c
index 3b072168..06e3bbf7 100644
--- a/skynet-src/malloc_hook.c
+++ b/skynet-src/malloc_hook.c
@@ -25,6 +25,10 @@ static mem_data mem_stats[SLOT_SIZE];
#include "jemalloc.h"
+// for skynet_lalloc use
+#define raw_realloc je_realloc
+#define raw_free je_free
+
static ssize_t*
get_allocated_field(uint32_t handle) {
int h = (int)(handle & (SLOT_SIZE - 1));
@@ -165,6 +169,10 @@ skynet_calloc(size_t nmemb,size_t size) {
#else
+// for skynet_lalloc use
+#define raw_realloc realloc
+#define raw_free free
+
void
memory_info_dump(void) {
skynet_error(NULL, "No jemalloc");
@@ -220,10 +228,10 @@ skynet_strdup(const char *str) {
void *
skynet_lalloc(void *ud, void *ptr, size_t osize, size_t nsize) {
if (nsize == 0) {
- skynet_free(ptr);
+ raw_free(ptr);
return NULL;
} else {
- return skynet_realloc(ptr, nsize);
+ return raw_realloc(ptr, nsize);
}
}
From 7138144a689374399baef55572a4d192d6c0486e Mon Sep 17 00:00:00 2001
From: huanzai <857763401@qq.com>
Date: Thu, 12 Nov 2015 11:15:50 +0800
Subject: [PATCH 94/97] Update lua-netpack.c
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
当长度等于0x10000时,read_size读出的值为0
---
lualib-src/lua-netpack.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lualib-src/lua-netpack.c b/lualib-src/lua-netpack.c
index 6e601e07..5fae0406 100644
--- a/lualib-src/lua-netpack.c
+++ b/lualib-src/lua-netpack.c
@@ -435,7 +435,7 @@ static int
lpack(lua_State *L) {
size_t len;
const char * ptr = tolstring(L, &len, 1);
- if (len > 0x10000) {
+ if (len >= 0x10000) {
return luaL_error(L, "Invalid size (too long) of data : %d", (int)len);
}
From 5edde990d6fd5cd8e8e25cc8e4e23d98ce0a5da4 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Thu, 12 Nov 2015 15:41:41 +0800
Subject: [PATCH 95/97] bugfix: skynet.fork use table.pack to pack table
---
lualib/skynet.lua | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/lualib/skynet.lua b/lualib/skynet.lua
index 2dd38f8d..0bc2d6e9 100644
--- a/lualib/skynet.lua
+++ b/lualib/skynet.lua
@@ -446,12 +446,10 @@ function skynet.dispatch_unknown_response(unknown)
return prev
end
-local tunpack = table.unpack
-
function skynet.fork(func,...)
- local args = { ... }
+ local args = table.pack(...)
local co = co_create(function()
- func(tunpack(args))
+ func(table.unpack(args,1,args.n))
end)
table.insert(fork_queue, co)
return co
From b72f0921d4ea9b9184fbfd675f422eb744309357 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Thu, 12 Nov 2015 16:21:44 +0800
Subject: [PATCH 96/97] remove unused local function
---
service/snaxd.lua | 8 --------
1 file changed, 8 deletions(-)
diff --git a/service/snaxd.lua b/service/snaxd.lua
index d27008be..1b8ddee6 100644
--- a/service/snaxd.lua
+++ b/service/snaxd.lua
@@ -26,14 +26,6 @@ end
local traceback = debug.traceback
-local function do_func(f, msg)
- return xpcall(f, traceback, table.unpack(msg))
-end
-
-local function dispatch(f, ...)
- return skynet.pack(f(...))
-end
-
local function return_f(f, ...)
return skynet.ret(skynet.pack(f(...)))
end
From d283d7fcaab86905f1d621a5ca25ec339f2ca220 Mon Sep 17 00:00:00 2001
From: Cloud Wu
Date: Thu, 12 Nov 2015 18:34:50 +0800
Subject: [PATCH 97/97] check close return value
---
skynet-src/socket_server.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/skynet-src/socket_server.c b/skynet-src/socket_server.c
index 2e26e24f..a3326b05 100644
--- a/skynet-src/socket_server.c
+++ b/skynet-src/socket_server.c
@@ -337,7 +337,9 @@ force_close(struct socket_server *ss, struct socket *s, struct socket_message *r
sp_del(ss->event_fd, s->fd);
}
if (s->type != SOCKET_TYPE_BIND) {
- close(s->fd);
+ if (close(s->fd) < 0) {
+ perror("close socket:");
+ }
}
s->type = SOCKET_TYPE_INVALID;
}