[mw-devel] MW3 r1284 - in trunk/src: . server
arthur at sucs.org
arthur at sucs.org
Thu Nov 8 15:19:10 GMT 2012
Author: arthur
Date: 2012-11-08 15:19:10 +0000 (Thu, 08 Nov 2012)
New Revision: 1284
Modified:
trunk/src/Makefile
trunk/src/incoming.c
trunk/src/ipc.c
trunk/src/server/servsock.c
trunk/src/socket.c
trunk/src/socket.h
Log:
reorder some socket code to prevent accessing already freed structures
Modified: trunk/src/Makefile
===================================================================
--- trunk/src/Makefile 2012-11-08 11:56:53 UTC (rev 1283)
+++ trunk/src/Makefile 2012-11-08 15:19:10 UTC (rev 1284)
@@ -93,6 +93,7 @@
done
make libdir="$(TESTDIR)" localstatedir="$(TESTDIR)"
make -C server libdir="$(TESTDIR)" localstatedir="$(TESTDIR)"
+ make -C webclient libdir="$(TESTDIR)" localstatedir="$(TESTDIR)"
testclean: clean
rm -rf "$(TESTDIR)"
Modified: trunk/src/incoming.c
===================================================================
--- trunk/src/incoming.c 2012-11-08 11:56:53 UTC (rev 1283)
+++ trunk/src/incoming.c 2012-11-08 15:19:10 UTC (rev 1284)
@@ -455,7 +455,13 @@
ipcmsg_destroy(msg);
msg = read_socket(ipcsock, 0);
}
- if (msg == NULL && !ipc_connected()) fprintf(stderr, "Server disconnected.\n");
+ if (msg == NULL && !ipc_connected()) {
+ if (ipcsock->fd != -1) {
+ close(ipcsock->fd);
+ ipcsock->fd = -1;
+ }
+ fprintf(stderr, "Server disconnected.\n");
+ }
if (cm_flags(user->chatmode,CM_ONCHAT,CM_MODE_ANY)) set_talk_rights(); else set_rights();
}
Modified: trunk/src/ipc.c
===================================================================
--- trunk/src/ipc.c 2012-11-08 11:56:53 UTC (rev 1283)
+++ trunk/src/ipc.c 2012-11-08 15:19:10 UTC (rev 1284)
@@ -30,6 +30,7 @@
/* we are not connected now */
if (ipcsock == NULL) return 0;
if (ipcsock->fd == -1) return 0;
+ if (ipcsock->state == IPCSTATE_ERROR) return 0;
/* everything must be fine */
return 1;
}
@@ -58,6 +59,7 @@
ipcsock = ipcconn_create();
ipcsock->fd = fd;
+ ipcsock->state = IPCSTATE_CONNECTED;
pid_t mypid = getpid();
ipc_message_t * msg = ipcmsg_create(FOURCC("HELO"), mypid);
@@ -79,6 +81,7 @@
{
if (ipcsock == NULL) return;
close(ipcsock->fd);
+ ipcsock->state = IPCSTATE_DELETED;
free(ipcsock);
ipcsock=NULL;
}
Modified: trunk/src/server/servsock.c
===================================================================
--- trunk/src/server/servsock.c 2012-11-08 11:56:53 UTC (rev 1283)
+++ trunk/src/server/servsock.c 2012-11-08 15:19:10 UTC (rev 1284)
@@ -81,8 +81,6 @@
/* add to list of all connections */
list_add_tail(&(new->list), &connection_list);
- INIT_LIST_HEAD(&(new->outq));
-
/* register interest in read events */
struct epoll_event ev;
bzero(&ev, sizeof(ev));
@@ -117,20 +115,22 @@
{
struct epoll_event ev;
- printf("Drop connection\n");
+ printf("Drop connection fd=%d\n", conn->fd);
bzero(&ev, sizeof(ev));
epoll_ctl(pollfd, EPOLL_CTL_DEL, conn->fd, &ev);
list_del_init(&conn->list);
if (conn->fd != -1) close(conn->fd);
conn->fd = -1;
- conn->state = IPCSTATE_ERROR;
who_delete(conn->addr);
+ conn->state = IPCSTATE_DELETED;
if (!list_empty(&conn->outq)) {
struct list_head *pos, *q;
list_for_each_safe(pos, q, &conn->outq) {
- ipc_message_t * msg = list_entry(pos, ipc_message_t, list);
- list_del(pos);
- ipcmsg_destroy(msg);
+ outq_msg_t * q = list_entry(pos, outq_msg_t, list);
+ list_del(&(q->list));
+ q->msg->refcount--;
+ if (q->msg->refcount <= 0) ipcmsg_destroy(q->msg);
+ free(q);
}
}
bzero(conn, sizeof(ipc_connection_t));
@@ -172,13 +172,10 @@
} else {
ipc_connection_t *c = event[i].data.ptr;
if (event[i].events & (EPOLLERR | EPOLLHUP | EPOLLRDHUP)) {
- drop_connection(c);
+ ipcconn_bad(c);
} else
if (event[i].events & (EPOLLIN | EPOLLPRI)) {
ipc_message_t *msg = read_socket(c, 1);
- if (c->fd == -1) {
- drop_connection(c);
- }else
while (msg != NULL) {
process_msg(c, msg);
msg=read_socket(c,0);
@@ -190,6 +187,15 @@
fprintf(stderr, "unexpected event on fd=%d.\n", c->fd);
}
}
+
+ /* check if we had to drop any connections and clean them away */
+ struct list_head *pos, *q;
+ list_for_each_safe(pos, q, &connection_list) {
+ ipc_connection_t * c = list_entry(pos, ipc_connection_t, list);
+ if (c->fd != -1 && c->state == IPCSTATE_ERROR) {
+ drop_connection(c);
+ }
+ }
}
/* end of events handling, do periodic stuff here */
}
@@ -203,6 +209,9 @@
void write_socket(ipc_connection_t * conn)
{
+ if (conn == NULL) return;
+ if (conn->state == IPCSTATE_ERROR) return;
+
if (list_empty(&conn->outq)) {
/* tx queue is empty, stop write events */
struct epoll_event ev;
Modified: trunk/src/socket.c
===================================================================
--- trunk/src/socket.c 2012-11-08 11:56:53 UTC (rev 1283)
+++ trunk/src/socket.c 2012-11-08 15:19:10 UTC (rev 1284)
@@ -6,6 +6,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
+#include <errno.h>
#include "socket.h"
/* generate FOURCC code from a string */
@@ -45,7 +46,8 @@
/* free a message */
void ipcmsg_destroy(ipc_message_t * msg)
{
- if (msg->body) free(msg->body);
+ if (msg == NULL) return;
+ if (msg->body != NULL) free(msg->body);
bzero(msg, sizeof(ipc_message_t));
free(msg);
}
@@ -82,8 +84,7 @@
/* mark this socket as bad/gone */
void ipcconn_bad(ipc_connection_t * conn)
{
- close(conn->fd);
- conn->fd = -1;
+ conn->state = IPCSTATE_ERROR;
}
/* create an empty connection socket struct */
@@ -92,6 +93,7 @@
ipc_connection_t * conn = malloc(sizeof(ipc_connection_t));
bzero(conn, sizeof(ipc_connection_t));
conn->fd = -1;
+ conn->state = IPCSTATE_ERROR;
INIT_LIST_HEAD(&(conn->outq));
return conn;
}
@@ -160,10 +162,11 @@
*/
ipc_message_t * read_socket(ipc_connection_t * conn, int doread)
{
- if (doread) {
+ if (doread && conn->state != IPCSTATE_ERROR && conn->fd != -1) {
int remain = sizeof(conn->p_buffer) - conn->i_buffer;
int ret = read(conn->fd, &conn->p_buffer[conn->i_buffer], remain);
if (ret <= 0) {
+ fprintf(stderr, "fd=%d bad read ret=%d %s\n", conn->fd, ret, strerror(errno));
ipcconn_bad(conn);
return NULL;
}
@@ -180,6 +183,8 @@
if (conn->incoming->head.len > 8192){
fprintf(stderr, "fd=%d Stupidly long message %d bytes.\n", conn->fd, conn->incoming->head.len);
+ ipcmsg_destroy(conn->incoming);
+ conn->incoming = NULL;
ipcconn_bad(conn);
return NULL;
}
Modified: trunk/src/socket.h
===================================================================
--- trunk/src/socket.h 2012-11-08 11:56:53 UTC (rev 1283)
+++ trunk/src/socket.h 2012-11-08 15:19:10 UTC (rev 1284)
@@ -10,7 +10,8 @@
enum ipcsock_state {
IPCSTATE_CONNECTED,
IPCSTATE_VALID,
- IPCSTATE_ERROR
+ IPCSTATE_ERROR,
+ IPCSTATE_DELETED
};
/* packed struct for socket ipc */
@@ -22,7 +23,6 @@
} __attribute__((packed)) ipc_msghead_t;
typedef struct {
- struct list_head list;
ipc_msghead_t head;
char * body;
int bodylen;
More information about the mw-devel
mailing list