Compare commits

..

12 Commits

Author SHA1 Message Date
Cloud Wu
2128a82571 update history, and release v0.3.2 2014-06-23 11:01:20 +08:00
Cloud Wu
d910686cb8 cluster bugfix : add socket.header to decode bigendian header 2014-06-21 18:03:08 +08:00
Cloud Wu
078ac2bcd2 bugfix: double free 2014-06-18 15:09:15 +08:00
云风
c7887cceb7 Merge pull request #119 from cloudwu/dev
release v0.3.1
2014-06-16 10:11:18 +08:00
Cloud Wu
4fbd433199 release v0.3.1 2014-06-16 10:10:18 +08:00
Cloud Wu
87d276caf6 typo fix 2014-06-12 17:28:54 +08:00
Cloud Wu
0f64e909fa big-endian encoding bson objectid 2014-06-11 15:11:18 +08:00
Cloud Wu
4bc2e800fd bugfix: lua mongo result 2014-06-09 18:08:23 +08:00
Cloud Wu
bf6501f2ee check mongo reply data stream 2014-06-09 17:43:40 +08:00
Cloud Wu
f92fc153e4 bugfix: in freebsd, libthr may call calloc before globalinit 2014-06-04 02:51:29 +00:00
Cloud Wu
c10e5412c0 invalid length may nagtive 2014-06-04 10:23:49 +08:00
Cloud Wu
9477cc8171 turn off memory hook in freeBSD 2014-06-03 12:35:00 +00:00
12 changed files with 85 additions and 39 deletions

View File

@@ -1,3 +1,15 @@
v0.3.2 (2014-6-23)
----------
* Bugifx : mongo driver and lua-bson . (objectid encoding, and gc problem when mongdo driver reply bson object).
* Bugfix : cluster (double free).
* Add socket.header() to decode big-endian package header (and fix the bug in cluster).
v0.3.1 (2014-6-16)
-----------
* Bugfix: lua mongo driver . Hold reply string before decode bson data.
* More check in bson decoding.
* Use big-endian for encoding bson objectid.
v0.3.0 (2014-6-2) v0.3.0 (2014-6-2)
----------- -----------
* Add cluster support * Add cluster support

View File

@@ -66,7 +66,7 @@ $(CSERVICE_PATH) :
define CSERVICE_TEMP define CSERVICE_TEMP
$$(CSERVICE_PATH)/$(1).so : service-src/service_$(1).c | $$(CSERVICE_PATH) $$(CSERVICE_PATH)/$(1).so : service-src/service_$(1).c | $$(CSERVICE_PATH)
$(CC) $$(CFLAGS) $$(SHARED) $$< -o $$@ -Iskynet-src $$(CC) $$(CFLAGS) $$(SHARED) $$< -o $$@ -Iskynet-src
endef endef
$(foreach v, $(CSERVICE), $(eval $(call CSERVICE_TEMP,$(v)))) $(foreach v, $(CSERVICE), $(eval $(call CSERVICE_TEMP,$(v))))

View File

@@ -1,6 +1,6 @@
## Build ## Build
Install autoconf first for jemalloc For linux, install autoconf first for jemalloc
``` ```
git clone git@github.com:cloudwu/skynet.git git clone git@github.com:cloudwu/skynet.git
@@ -15,6 +15,8 @@ export PLAT=linux
make make
``` ```
For freeBSD , use gmake instead of make .
## Test ## Test
Run these in different console Run these in different console

View File

@@ -68,6 +68,13 @@ struct bson_reader {
int size; int size;
}; };
static inline int32_t
get_length(const uint8_t * data) {
const uint8_t * b = (const uint8_t *)data;
int32_t len = b[0] | b[1]<<8 | b[2]<<16 | b[3]<<24;
return len;
}
static inline void static inline void
bson_destroy(struct bson *b) { bson_destroy(struct bson *b) {
if (b->ptr != b->buffer) { if (b->ptr != b->buffer) {
@@ -532,8 +539,8 @@ unpack_dict(lua_State *L, struct bson_reader *br, bool array) {
break; break;
case BSON_STRING: { case BSON_STRING: {
int sz = read_int32(L, &t); int sz = read_int32(L, &t);
if (sz == 0) { if (sz <= 0) {
luaL_error(L, "Invalid bson string , length = 0"); luaL_error(L, "Invalid bson string , length = %d", sz);
} }
lua_pushlstring(L, read_bytes(L, &t, sz), sz-1); lua_pushlstring(L, read_bytes(L, &t, sz), sz-1);
break; break;
@@ -644,7 +651,7 @@ static int
lmakeindex(lua_State *L) { lmakeindex(lua_State *L) {
int32_t *bson = luaL_checkudata(L,1,"bson"); int32_t *bson = luaL_checkudata(L,1,"bson");
const uint8_t * start = (const uint8_t *)bson; const uint8_t * start = (const uint8_t *)bson;
struct bson_reader br = { start+4, *bson - 5 }; struct bson_reader br = { start+4, get_length(start) - 5 };
lua_newtable(L); lua_newtable(L);
for (;;) { for (;;) {
@@ -820,7 +827,9 @@ ldecode(lua_State *L) {
if (data == NULL) { if (data == NULL) {
return 0; return 0;
} }
struct bson_reader br = { (const uint8_t *)data , *data }; const uint8_t * b = (const uint8_t *)data;
int32_t len = get_length(b);
struct bson_reader br = { b , len };
unpack_dict(L, &br, false); unpack_dict(L, &br, false);
@@ -1140,14 +1149,14 @@ lobjectid(lua_State *L) {
} }
} else { } else {
time_t ti = time(NULL); time_t ti = time(NULL);
oid[2] = ti & 0xff; oid[2] = (ti>>24) & 0xff;
oid[3] = (ti>>8) & 0xff; oid[3] = (ti>>16) & 0xff;
oid[4] = (ti>>16) & 0xff; oid[4] = (ti>>8) & 0xff;
oid[5] = (ti>>24) & 0xff; oid[5] = ti & 0xff;
memcpy(oid+6 , oid_header, 5); memcpy(oid+6 , oid_header, 5);
oid[11] = oid_counter & 0xff; oid[11] = (oid_counter>>16) & 0xff;
oid[12] = (oid_counter>>8) & 0xff; oid[12] = (oid_counter>>8) & 0xff;
oid[13] = (oid_counter>>16) & 0xff; oid[13] = oid_counter & 0xff;
++oid_counter; ++oid_counter;
} }
lua_pushlstring( L, (const char *)oid, 14); lua_pushlstring( L, (const char *)oid, 14);

View File

@@ -153,6 +153,8 @@ lunpackrequest(lua_State *L) {
static int static int
lpackresponse(lua_State *L) { lpackresponse(lua_State *L) {
uint32_t session = luaL_checkunsigned(L,1); uint32_t session = luaL_checkunsigned(L,1);
// clusterd.lua:command.socket call lpackresponse,
// and the msg/sz is return by skynet.rawcall , so don't free(msg)
void * msg = lua_touserdata(L,2); void * msg = lua_touserdata(L,2);
size_t sz = luaL_checkunsigned(L, 3); size_t sz = luaL_checkunsigned(L, 3);
@@ -161,8 +163,6 @@ lpackresponse(lua_State *L) {
fill_uint32(buf+2, session); fill_uint32(buf+2, session);
memcpy(buf+6,msg,sz); memcpy(buf+6,msg,sz);
skynet_free(msg);
lua_pushlstring(L, (const char *)buf, sz+6); lua_pushlstring(L, (const char *)buf, sz+6);
return 1; return 1;

View File

@@ -260,6 +260,13 @@ op_reply(lua_State *L) {
lua_pushnil(L); lua_pushnil(L);
lua_rawseti(L, 2, i); lua_rawseti(L, 2, i);
} }
} else {
if (sz >= 4) {
sz -= get_length((document)doc);
}
}
if (sz != 0) {
return luaL_error(L, "Invalid result bson document");
} }
lua_pushboolean(L,1); lua_pushboolean(L,1);
lua_pushinteger(L, id); lua_pushinteger(L, id);

View File

@@ -188,10 +188,29 @@ pop_lstring(lua_State *L, struct socket_buffer *sb, int sz, int skip) {
luaL_pushresult(&b); luaL_pushresult(&b);
} }
static int
lheader(lua_State *L) {
size_t len;
const uint8_t * s = (const uint8_t *)luaL_checklstring(L, 1, &len);
if (len > 4 || len < 1) {
return luaL_error(L, "Invalid read %s", s);
}
int i;
size_t sz = 0;
for (i=0;i<(int)len;i++) {
sz <<= 8;
sz |= s[i];
}
lua_pushunsigned(L, sz);
return 1;
}
/* /*
userdata send_buffer userdata send_buffer
table pool table pool
integer sz or string (big endian) integer sz
*/ */
static int static int
lpopbuffer(lua_State *L) { lpopbuffer(lua_State *L) {
@@ -200,23 +219,7 @@ lpopbuffer(lua_State *L) {
return luaL_error(L, "Need buffer object at param 1"); return luaL_error(L, "Need buffer object at param 1");
} }
luaL_checktype(L,2,LUA_TTABLE); luaL_checktype(L,2,LUA_TTABLE);
int type = lua_type(L,3); int sz = luaL_checkinteger(L,3);
int sz;
if (type == LUA_TNUMBER) {
sz = lua_tointeger(L,3);
} else {
size_t len;
const uint8_t * s = (const uint8_t *)luaL_checklstring(L, 3, &len);
if (len > 4 || len < 1) {
return luaL_error(L, "Invalid read %s", s);
}
int i;
sz = 0;
for (i=0;i<(int)len;i++) {
sz <<= 8;
sz |= s[i];
}
}
if (sb->size < sz || sz == 0) { if (sb->size < sz || sz == 0) {
lua_pushnil(L); lua_pushnil(L);
} else { } else {
@@ -485,6 +488,7 @@ luaopen_socketdriver(lua_State *L) {
{ "clear", lclearbuffer }, { "clear", lclearbuffer },
{ "readline", lreadline }, { "readline", lreadline },
{ "str2p", lstr2p }, { "str2p", lstr2p },
{ "header", lheader },
{ "unpack", lunpack }, { "unpack", lunpack },
{ NULL, NULL }, { NULL, NULL },

View File

@@ -98,7 +98,7 @@ function mongo.client( conf )
host = obj.host, host = obj.host,
port = obj.port, port = obj.port,
response = dispatch_reply, response = dispatch_reply,
auth = mongo_auth(conf), auth = mongo_auth(obj),
} }
setmetatable(obj, client_meta) setmetatable(obj, client_meta)
obj.__sock:connect(true) -- try connect only once obj.__sock:connect(true) -- try connect only once
@@ -167,7 +167,9 @@ function mongo_db:runCommand(cmd,cmd_v,...)
bson_cmd = bson_encode_order(cmd,cmd_v,...) bson_cmd = bson_encode_order(cmd,cmd_v,...)
end end
local pack = driver.query(request_id, 0, self.__cmd, 0, 1, bson_cmd) local pack = driver.query(request_id, 0, self.__cmd, 0, 1, bson_cmd)
local doc = sock:request(pack, request_id).document -- we must hold req (req.data), because req.document is a lightuserdata, it's a pointer to the string (req.data)
local req = sock:request(pack, request_id)
local doc = req.document
return bson_decode(doc) return bson_decode(doc)
end end
@@ -224,7 +226,9 @@ function mongo_collection:findOne(query, selector)
local request_id = conn:genId() local request_id = conn:genId()
local sock = conn.__sock local sock = conn.__sock
local pack = driver.query(request_id, 0, self.full_name, 0, 1, query and bson_encode(query) or empty_bson, selector and bson_encode(selector)) local pack = driver.query(request_id, 0, self.full_name, 0, 1, query and bson_encode(query) or empty_bson, selector and bson_encode(selector))
local doc = sock:request(pack, request_id).document -- we must hold req (req.data), because req.document is a lightuserdata, it's a pointer to the string (req.data)
local req = sock:request(pack, request_id)
local doc = req.document
return bson_decode(doc) return bson_decode(doc)
end end

View File

@@ -266,6 +266,7 @@ end
socket.write = assert(driver.send) socket.write = assert(driver.send)
socket.lwrite = assert(driver.lsend) socket.lwrite = assert(driver.lsend)
socket.header = assert(driver.header)
function socket.invalid(id) function socket.invalid(id)
return socket_pool[id] == nil return socket_pool[id] == nil

View File

@@ -31,7 +31,7 @@ macosx : EXPORT :=
macosx linux : SKYNET_LIBS += -ldl macosx linux : SKYNET_LIBS += -ldl
linux freebsd : SKYNET_LIBS += -lrt linux freebsd : SKYNET_LIBS += -lrt
# Turn off jemalloc and malloc hook on macosx # Turn off jemalloc and malloc hook on macosx and freebsd
macosx : MALLOC_STATICLIB := macosx : MALLOC_STATICLIB :=
macosx : SKYNET_DEFINES :=-DNOUSE_JEMALLOC macosx : SKYNET_DEFINES :=-DNOUSE_JEMALLOC

View File

@@ -10,7 +10,7 @@ local node_session = {}
local command = {} local command = {}
local function read_response(sock) local function read_response(sock)
local sz = sock:read(2) local sz = socket.header(sock:read(2))
local msg = sock:read(sz) local msg = sock:read(sz)
return cluster.unpackresponse(msg) -- session, ok, data return cluster.unpackresponse(msg) -- session, ok, data
end end

View File

@@ -52,6 +52,7 @@ struct skynet_context {
struct skynet_node { struct skynet_node {
int total; int total;
int init;
uint32_t monitor_exit; uint32_t monitor_exit;
pthread_key_t handle_key; pthread_key_t handle_key;
}; };
@@ -75,8 +76,13 @@ context_dec() {
uint32_t uint32_t
skynet_current_handle(void) { skynet_current_handle(void) {
if (G_NODE.init) {
void * handle = pthread_getspecific(G_NODE.handle_key); void * handle = pthread_getspecific(G_NODE.handle_key);
return (uint32_t)(uintptr_t)handle; return (uint32_t)(uintptr_t)handle;
} else {
uintptr_t v = (uint32_t)(-THREAD_MAIN);
return v;
}
} }
static void static void
@@ -650,6 +656,7 @@ void
skynet_globalinit(void) { skynet_globalinit(void) {
G_NODE.total = 0; G_NODE.total = 0;
G_NODE.monitor_exit = 0; G_NODE.monitor_exit = 0;
G_NODE.init = 1;
if (pthread_key_create(&G_NODE.handle_key, NULL)) { if (pthread_key_create(&G_NODE.handle_key, NULL)) {
fprintf(stderr, "pthread_key_create failed"); fprintf(stderr, "pthread_key_create failed");
exit(1); exit(1);