mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-24 20:23:06 +00:00
more error message for socket, and close listen socket when reach limit of open files. See Issue #339
This commit is contained in:
@@ -101,17 +101,24 @@ function gateserver.start(handler)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function MSG.close(fd)
|
function MSG.close(fd)
|
||||||
if handler.disconnect then
|
if fd ~= socket then
|
||||||
handler.disconnect(fd)
|
if handler.disconnect then
|
||||||
|
handler.disconnect(fd)
|
||||||
|
end
|
||||||
|
close_fd(fd)
|
||||||
end
|
end
|
||||||
close_fd(fd)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function MSG.error(fd, msg)
|
function MSG.error(fd, msg)
|
||||||
if handler.error then
|
if fd == socket then
|
||||||
handler.error(fd, msg)
|
socketdriver.close(fd)
|
||||||
|
skynet.error(msg)
|
||||||
|
else
|
||||||
|
if handler.error then
|
||||||
|
handler.error(fd, msg)
|
||||||
|
end
|
||||||
|
close_fd(fd)
|
||||||
end
|
end
|
||||||
close_fd(fd)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function MSG.warning(fd, size)
|
function MSG.warning(fd, size)
|
||||||
|
|||||||
@@ -106,16 +106,17 @@ socket_message[4] = function(id, newid, addr)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- SKYNET_SOCKET_TYPE_ERROR = 5
|
-- SKYNET_SOCKET_TYPE_ERROR = 5
|
||||||
socket_message[5] = function(id)
|
socket_message[5] = function(id, _, err)
|
||||||
local s = socket_pool[id]
|
local s = socket_pool[id]
|
||||||
if s == nil then
|
if s == nil then
|
||||||
skynet.error("socket: error on unknown", id)
|
skynet.error("socket: error on unknown", id, err)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if s.connected then
|
if s.connected or s.connecting then
|
||||||
skynet.error("socket: error on", id)
|
skynet.error("socket: error on", id, err)
|
||||||
end
|
end
|
||||||
s.connected = false
|
s.connected = false
|
||||||
|
driver.close(id)
|
||||||
|
|
||||||
wakeup(s)
|
wakeup(s)
|
||||||
end
|
end
|
||||||
@@ -170,6 +171,7 @@ local function connect(id, func)
|
|||||||
id = id,
|
id = id,
|
||||||
buffer = newbuffer,
|
buffer = newbuffer,
|
||||||
connected = false,
|
connected = false,
|
||||||
|
connecting = true,
|
||||||
read_required = false,
|
read_required = false,
|
||||||
co = false,
|
co = false,
|
||||||
callback = func,
|
callback = func,
|
||||||
@@ -177,6 +179,7 @@ local function connect(id, func)
|
|||||||
}
|
}
|
||||||
socket_pool[id] = s
|
socket_pool[id] = s
|
||||||
suspend(s)
|
suspend(s)
|
||||||
|
s.connecting = nil
|
||||||
if s.connected then
|
if s.connected then
|
||||||
return id
|
return id
|
||||||
else
|
else
|
||||||
@@ -221,7 +224,7 @@ function socket.close(id)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
if s.connected then
|
if s.connected then
|
||||||
driver.close(s.id)
|
driver.close(id)
|
||||||
-- notice: call socket.close in __gc should be carefully,
|
-- notice: call socket.close in __gc should be carefully,
|
||||||
-- because skynet.wait never return in __gc, so driver.clear may not be called
|
-- because skynet.wait never return in __gc, so driver.clear may not be called
|
||||||
if s.co then
|
if s.co then
|
||||||
|
|||||||
@@ -36,7 +36,11 @@ forward_message(int type, bool padding, struct socket_message * result) {
|
|||||||
size_t sz = sizeof(*sm);
|
size_t sz = sizeof(*sm);
|
||||||
if (padding) {
|
if (padding) {
|
||||||
if (result->data) {
|
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 {
|
} else {
|
||||||
result->data = "";
|
result->data = "";
|
||||||
}
|
}
|
||||||
@@ -86,7 +90,7 @@ skynet_socket_poll() {
|
|||||||
forward_message(SKYNET_SOCKET_TYPE_CONNECT, true, &result);
|
forward_message(SKYNET_SOCKET_TYPE_CONNECT, true, &result);
|
||||||
break;
|
break;
|
||||||
case SOCKET_ERROR:
|
case SOCKET_ERROR:
|
||||||
forward_message(SKYNET_SOCKET_TYPE_ERROR, false, &result);
|
forward_message(SKYNET_SOCKET_TYPE_ERROR, true, &result);
|
||||||
break;
|
break;
|
||||||
case SOCKET_ACCEPT:
|
case SOCKET_ACCEPT:
|
||||||
forward_message(SKYNET_SOCKET_TYPE_ACCEPT, true, &result);
|
forward_message(SKYNET_SOCKET_TYPE_ACCEPT, true, &result);
|
||||||
|
|||||||
@@ -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 );
|
status = getaddrinfo( request->host, port, &ai_hints, &ai_list );
|
||||||
if ( status != 0 ) {
|
if ( status != 0 ) {
|
||||||
|
result->data = (void *)gai_strerror(status);
|
||||||
goto _failed;
|
goto _failed;
|
||||||
}
|
}
|
||||||
int sock= -1;
|
int sock= -1;
|
||||||
@@ -428,12 +429,14 @@ open_socket(struct socket_server *ss, struct request_open * request, struct sock
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sock < 0) {
|
if (sock < 0) {
|
||||||
|
result->data = strerror(errno);
|
||||||
goto _failed;
|
goto _failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
ns = new_fd(ss, id, sock, PROTOCOL_TCP, request->opaque, true);
|
ns = new_fd(ss, id, sock, PROTOCOL_TCP, request->opaque, true);
|
||||||
if (ns == NULL) {
|
if (ns == NULL) {
|
||||||
close(sock);
|
close(sock);
|
||||||
|
result->data = "reach skynet socket number limit";
|
||||||
goto _failed;
|
goto _failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -762,7 +765,7 @@ _failed:
|
|||||||
result->opaque = request->opaque;
|
result->opaque = request->opaque;
|
||||||
result->id = id;
|
result->id = id;
|
||||||
result->ud = 0;
|
result->ud = 0;
|
||||||
result->data = NULL;
|
result->data = "reach skynet socket number limit";
|
||||||
ss->slot[HASH_ID(id)].type = SOCKET_TYPE_INVALID;
|
ss->slot[HASH_ID(id)].type = SOCKET_TYPE_INVALID;
|
||||||
|
|
||||||
return SOCKET_ERROR;
|
return SOCKET_ERROR;
|
||||||
@@ -803,7 +806,7 @@ bind_socket(struct socket_server *ss, struct request_bind *request, struct socke
|
|||||||
result->ud = 0;
|
result->ud = 0;
|
||||||
struct socket *s = new_fd(ss, id, request->fd, PROTOCOL_TCP, request->opaque, true);
|
struct socket *s = new_fd(ss, id, request->fd, PROTOCOL_TCP, request->opaque, true);
|
||||||
if (s == NULL) {
|
if (s == NULL) {
|
||||||
result->data = NULL;
|
result->data = "reach skynet socket number limit";
|
||||||
return SOCKET_ERROR;
|
return SOCKET_ERROR;
|
||||||
}
|
}
|
||||||
sp_nonblocking(request->fd);
|
sp_nonblocking(request->fd);
|
||||||
@@ -821,11 +824,13 @@ start_socket(struct socket_server *ss, struct request_start *request, struct soc
|
|||||||
result->data = NULL;
|
result->data = NULL;
|
||||||
struct socket *s = &ss->slot[HASH_ID(id)];
|
struct socket *s = &ss->slot[HASH_ID(id)];
|
||||||
if (s->type == SOCKET_TYPE_INVALID || s->id !=id) {
|
if (s->type == SOCKET_TYPE_INVALID || s->id !=id) {
|
||||||
|
result->data = "invalid socket";
|
||||||
return SOCKET_ERROR;
|
return SOCKET_ERROR;
|
||||||
}
|
}
|
||||||
if (s->type == SOCKET_TYPE_PACCEPT || s->type == SOCKET_TYPE_PLISTEN) {
|
if (s->type == SOCKET_TYPE_PACCEPT || s->type == SOCKET_TYPE_PLISTEN) {
|
||||||
if (sp_add(ss->event_fd, s->fd, s)) {
|
if (sp_add(ss->event_fd, s->fd, s)) {
|
||||||
s->type = SOCKET_TYPE_INVALID;
|
s->type = SOCKET_TYPE_INVALID;
|
||||||
|
result->data = strerror(errno);
|
||||||
return SOCKET_ERROR;
|
return SOCKET_ERROR;
|
||||||
}
|
}
|
||||||
s->type = (s->type == SOCKET_TYPE_PACCEPT) ? SOCKET_TYPE_CONNECTED : SOCKET_TYPE_LISTEN;
|
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->opaque = s->opaque;
|
||||||
result->id = s->id;
|
result->id = s->id;
|
||||||
result->ud = 0;
|
result->ud = 0;
|
||||||
result->data = NULL;
|
result->data = "protocol mismatch";
|
||||||
|
|
||||||
return SOCKET_ERROR;
|
return SOCKET_ERROR;
|
||||||
}
|
}
|
||||||
@@ -995,6 +1000,7 @@ forward_message_tcp(struct socket_server *ss, struct socket *s, struct socket_me
|
|||||||
default:
|
default:
|
||||||
// close when error
|
// close when error
|
||||||
force_close(ss, s, result);
|
force_close(ss, s, result);
|
||||||
|
result->data = strerror(errno);
|
||||||
return SOCKET_ERROR;
|
return SOCKET_ERROR;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1055,6 +1061,7 @@ forward_message_udp(struct socket_server *ss, struct socket *s, struct socket_me
|
|||||||
default:
|
default:
|
||||||
// close when error
|
// close when error
|
||||||
force_close(ss, s, result);
|
force_close(ss, s, result);
|
||||||
|
result->data = strerror(errno);
|
||||||
return SOCKET_ERROR;
|
return SOCKET_ERROR;
|
||||||
}
|
}
|
||||||
return -1;
|
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);
|
int code = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &error, &len);
|
||||||
if (code < 0 || error) {
|
if (code < 0 || error) {
|
||||||
force_close(ss,s, result);
|
force_close(ss,s, result);
|
||||||
|
result->data = strerror(errno);
|
||||||
return SOCKET_ERROR;
|
return SOCKET_ERROR;
|
||||||
} else {
|
} else {
|
||||||
s->type = SOCKET_TYPE_CONNECTED;
|
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
|
static int
|
||||||
report_accept(struct socket_server *ss, struct socket *s, struct socket_message *result) {
|
report_accept(struct socket_server *ss, struct socket *s, struct socket_message *result) {
|
||||||
union sockaddr_all u;
|
union sockaddr_all u;
|
||||||
socklen_t len = sizeof(u);
|
socklen_t len = sizeof(u);
|
||||||
int client_fd = accept(s->fd, &u.s, &len);
|
int client_fd = accept(s->fd, &u.s, &len);
|
||||||
if (client_fd < 0) {
|
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);
|
int id = reserve_id(ss);
|
||||||
if (id < 0) {
|
if (id < 0) {
|
||||||
@@ -1203,11 +1219,16 @@ socket_server_poll(struct socket_server *ss, struct socket_message * result, int
|
|||||||
switch (s->type) {
|
switch (s->type) {
|
||||||
case SOCKET_TYPE_CONNECTING:
|
case SOCKET_TYPE_CONNECTING:
|
||||||
return report_connect(ss, s, result);
|
return report_connect(ss, s, result);
|
||||||
case SOCKET_TYPE_LISTEN:
|
case SOCKET_TYPE_LISTEN: {
|
||||||
if (report_accept(ss, s, result)) {
|
int ok = report_accept(ss, s, result);
|
||||||
|
if (ok > 0) {
|
||||||
return SOCKET_ACCEPT;
|
return SOCKET_ACCEPT;
|
||||||
|
} if (ok < 0 ) {
|
||||||
|
return SOCKET_ERROR;
|
||||||
}
|
}
|
||||||
|
// when ok == 0, retry
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case SOCKET_TYPE_INVALID:
|
case SOCKET_TYPE_INVALID:
|
||||||
fprintf(stderr, "socket-server: invalid socket\n");
|
fprintf(stderr, "socket-server: invalid socket\n");
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user