diff options
author | Andrew Tridgell <tridge@samba.org> | 2007-10-22 16:41:11 +1000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2007-10-22 16:41:11 +1000 |
commit | 8e22bca5cab9a5d28e45c11de8844c6c7a24d5e3 (patch) | |
tree | 740576ddb4d93d01d2d789e90eb668970e285dab /ctdb/tcp/tcp_connect.c | |
parent | 2d8afd85d5b851f979169aac1d9e9a590246d785 (diff) | |
download | samba-8e22bca5cab9a5d28e45c11de8844c6c7a24d5e3.tar.gz samba-8e22bca5cab9a5d28e45c11de8844c6c7a24d5e3.tar.xz samba-8e22bca5cab9a5d28e45c11de8844c6c7a24d5e3.zip |
fixed a double close of a socket, leading to an EPOLL error
(This used to be ctdb commit bbe8ad842bdfedd37ef14a6be07ad939113fe9b1)
Diffstat (limited to 'ctdb/tcp/tcp_connect.c')
-rw-r--r-- | ctdb/tcp/tcp_connect.c | 60 |
1 files changed, 36 insertions, 24 deletions
diff --git a/ctdb/tcp/tcp_connect.c b/ctdb/tcp/tcp_connect.c index ad9ce954ff..3548f82ed7 100644 --- a/ctdb/tcp/tcp_connect.c +++ b/ctdb/tcp/tcp_connect.c @@ -26,6 +26,26 @@ #include "ctdb_tcp.h" /* + stop any connecting (established or pending) to a node + */ +void ctdb_tcp_stop_connection(struct ctdb_node *node) +{ + struct ctdb_tcp_node *tnode = talloc_get_type( + node->private_data, struct ctdb_tcp_node); + + ctdb_queue_set_fd(tnode->out_queue, -1); + talloc_free(tnode->connect_te); + talloc_free(tnode->connect_fde); + tnode->connect_fde = NULL; + tnode->connect_te = NULL; + if (tnode->fd != -1) { + close(tnode->fd); + tnode->fd = -1; + } +} + + +/* called when a complete packet has come in - should not happen on this socket */ void ctdb_tcp_tnode_cb(uint8_t *data, size_t cnt, void *private_data) @@ -38,12 +58,9 @@ void ctdb_tcp_tnode_cb(uint8_t *data, size_t cnt, void *private_data) node->ctdb->upcalls->node_dead(node); } - /* start a new connect cycle to try to re-establish the - link */ - ctdb_queue_set_fd(tnode->out_queue, -1); - tnode->fd = -1; - event_add_timed(node->ctdb->ev, tnode, timeval_zero(), - ctdb_tcp_node_connect, node); + ctdb_tcp_stop_connection(node); + tnode->connect_te = event_add_timed(node->ctdb->ev, tnode, timeval_zero(), + ctdb_tcp_node_connect, node); } /* @@ -66,23 +83,24 @@ static void ctdb_node_connect_write(struct event_context *ev, struct fd_event *f if (getsockopt(tnode->fd, SOL_SOCKET, SO_ERROR, &error, &len) != 0 || error != 0) { - talloc_free(tnode->connect_fde); - tnode->connect_fde = NULL; - close(tnode->fd); - tnode->fd = -1; - event_add_timed(ctdb->ev, tnode, timeval_current_ofs(1, 0), - ctdb_tcp_node_connect, node); + ctdb_tcp_stop_connection(node); + tnode->connect_te = event_add_timed(ctdb->ev, tnode, + timeval_current_ofs(1, 0), + ctdb_tcp_node_connect, node); return; } talloc_free(tnode->connect_fde); tnode->connect_fde = NULL; - + setsockopt(tnode->fd,IPPROTO_TCP,TCP_NODELAY,(char *)&one,sizeof(one)); setsockopt(tnode->fd,SOL_SOCKET,SO_KEEPALIVE,(char *)&one,sizeof(one)); ctdb_queue_set_fd(tnode->out_queue, tnode->fd); + /* the queue subsystem now owns this fd */ + tnode->fd = -1; + /* tell the ctdb layer we are connected */ node->ctdb->upcalls->node_connected(node); } @@ -117,12 +135,7 @@ void ctdb_tcp_node_connect(struct event_context *ev, struct timed_event *te, struct sockaddr_in sock_in; struct sockaddr_in sock_out; - if (tnode->fd != -1) { - talloc_free(tnode->connect_fde); - tnode->connect_fde = NULL; - close(tnode->fd); - tnode->fd = -1; - } + ctdb_tcp_stop_connection(node); tnode->fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); @@ -159,11 +172,10 @@ void ctdb_tcp_node_connect(struct event_context *ev, struct timed_event *te, if (connect(tnode->fd, (struct sockaddr *)&sock_out, sizeof(sock_out)) != 0 && errno != EINPROGRESS) { - /* try again once a second */ - close(tnode->fd); - tnode->fd = -1; - event_add_timed(ctdb->ev, tnode, timeval_current_ofs(1, 0), - ctdb_tcp_node_connect, node); + ctdb_tcp_stop_connection(node); + tnode->connect_te = event_add_timed(ctdb->ev, tnode, + timeval_current_ofs(1, 0), + ctdb_tcp_node_connect, node); return; } |