From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id 561402A4DE for ; Wed, 20 Mar 2019 06:49:24 -0400 (EDT) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 8Np-tYZ4K1pv for ; Wed, 20 Mar 2019 06:49:24 -0400 (EDT) Received: from smtpng2.m.smailru.net (smtpng2.m.smailru.net [94.100.179.3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id 0C2812A4D2 for ; Wed, 20 Mar 2019 06:49:24 -0400 (EDT) From: Vladislav Shpilevoy Subject: [tarantool-patches] [PATCH 5/6] test: differentiate blocked and closed swim fake fds Date: Wed, 20 Mar 2019 13:49:18 +0300 Message-Id: In-Reply-To: References: In-Reply-To: References: Sender: tarantool-patches-bounce@freelists.org Errors-to: tarantool-patches-bounce@freelists.org Reply-To: tarantool-patches@freelists.org List-Help: List-Unsubscribe: List-software: Ecartis version 1.0.0 List-Id: tarantool-patches List-Subscribe: List-Owner: List-post: List-Archive: To: tarantool-patches@freelists.org Cc: kostja@tarantool.org SWIM's fake file descriptors were implemented to test SWIM with virtual time and fully controlled network with immediate packet delivery. One of their features - API to block a file descriptor and test various failures about it. But blocked fake fd looks the same as closed fd, and it can confuse new test's author. Now if an fd is not unblocked at the end of a test, it leads to a crash. This commit fixes that via adding explicit difference between blocked and closed fd. Part of #3234 --- test/unit/swim_test_transport.c | 53 +++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/test/unit/swim_test_transport.c b/test/unit/swim_test_transport.c index d6591e969..d1c3e97d7 100644 --- a/test/unit/swim_test_transport.c +++ b/test/unit/swim_test_transport.c @@ -90,10 +90,17 @@ struct swim_fd { /** File descriptor number visible to libev. */ int evfd; /** - * Link in the list of opened descriptors. Used to feed - * them all EV_WRITE. + * True, if the descriptor is opened and can receive new + * messages. Regardless of blocked or not. In case of + * blocked, new messages are queued, but not delivered. */ - struct rlist in_opened; + bool is_opened; + + /** + * Link in the list of opened and non-blocked descriptors. + * Used to feed them all EV_WRITE. + */ + struct rlist in_active; /** Queue of received, but not processed packets. */ struct rlist recv_queue; /** Queue of sent, but not received packets. */ @@ -103,23 +110,22 @@ struct swim_fd { /** Table of fake file descriptors. */ static struct swim_fd swim_fd[FAKE_FD_NUMBER]; /** - * List of opened file descriptors. Used to avoid fullscan of the + * List of active file descriptors. Used to avoid fullscan of the * table. */ -static RLIST_HEAD(swim_fd_opened); +static RLIST_HEAD(swim_fd_active); /** Open a fake file descriptor. */ static inline int swim_fd_open(struct swim_fd *fd) { - if (! rlist_empty(&fd->in_opened)) { + if (fd->is_opened) { errno = EADDRINUSE; diag_set(SocketError, "test_socket:1", "bind"); return -1; } - rlist_add_tail_entry(&swim_fd_opened, fd, in_opened); - rlist_create(&fd->recv_queue); - rlist_create(&fd->send_queue); + fd->is_opened = true; + rlist_add_tail_entry(&swim_fd_active, fd, in_active); return 0; } @@ -127,12 +133,15 @@ swim_fd_open(struct swim_fd *fd) static inline void swim_fd_close(struct swim_fd *fd) { + if (! fd->is_opened) + return; struct swim_test_packet *i, *tmp; rlist_foreach_entry_safe(i, &fd->recv_queue, in_queue, tmp) swim_test_packet_delete(i); rlist_foreach_entry_safe(i, &fd->send_queue, in_queue, tmp) swim_test_packet_delete(i); - rlist_del_entry(fd, in_opened); + rlist_del_entry(fd, in_active); + fd->is_opened = false; } void @@ -140,7 +149,8 @@ swim_test_transport_init(void) { for (int i = 0, evfd = FAKE_FD_BASE; i < FAKE_FD_NUMBER; ++i, ++evfd) { swim_fd[i].evfd = evfd; - rlist_create(&swim_fd[i].in_opened); + swim_fd[i].is_opened = false; + rlist_create(&swim_fd[i].in_active); rlist_create(&swim_fd[i].recv_queue); rlist_create(&swim_fd[i].send_queue); } @@ -172,6 +182,7 @@ swim_transport_send(struct swim_transport *transport, const void *data, swim_test_packet_new(data, size, &transport->addr, (const struct sockaddr_in *) addr); struct swim_fd *src = &swim_fd[transport->fd - FAKE_FD_BASE]; + assert(src->is_opened); rlist_add_tail_entry(&src->send_queue, p, in_queue); return size; } @@ -188,6 +199,7 @@ swim_transport_recv(struct swim_transport *transport, void *buffer, size_t size, * Pop a packet from a receving queue. */ struct swim_fd *dst = &swim_fd[transport->fd - FAKE_FD_BASE]; + assert(dst->is_opened); struct swim_test_packet *p = rlist_shift_entry(&dst->recv_queue, struct swim_test_packet, in_queue); @@ -236,16 +248,16 @@ void swim_test_transport_block_fd(int fd) { struct swim_fd *sfd = &swim_fd[fd - FAKE_FD_BASE]; - assert(! rlist_empty(&sfd->in_opened)); - rlist_del_entry(sfd, in_opened); + assert(! rlist_empty(&sfd->in_active)); + rlist_del_entry(sfd, in_active); } void swim_test_transport_unblock_fd(int fd) { struct swim_fd *sfd = &swim_fd[fd - FAKE_FD_BASE]; - assert(rlist_empty(&sfd->in_opened)); - rlist_add_tail_entry(&swim_fd_opened, sfd, in_opened); + if (sfd->is_opened && rlist_empty(&sfd->in_active)) + rlist_add_tail_entry(&swim_fd_active, sfd, in_active); } /** Send one packet to destination's recv queue. */ @@ -257,8 +269,11 @@ swim_fd_send_packet(struct swim_fd *fd) struct swim_test_packet *p = rlist_shift_entry(&fd->send_queue, struct swim_test_packet, in_queue); - int dst_i = ntohs(p->dst.sin_port); - rlist_add_tail_entry(&swim_fd[dst_i].recv_queue, p, in_queue); + struct swim_fd *dst = &swim_fd[ntohs(p->dst.sin_port)]; + if (dst->is_opened) + rlist_add_tail_entry(&dst->recv_queue, p, in_queue); + else + swim_test_packet_delete(p); } void @@ -269,11 +284,11 @@ swim_transport_do_loop_step(struct ev_loop *loop) * Reversed because libev invokes events in reversed * order. So this reverse + libev reverse = normal order. */ - rlist_foreach_entry_reverse(fd, &swim_fd_opened, in_opened) { + rlist_foreach_entry_reverse(fd, &swim_fd_active, in_active) { swim_fd_send_packet(fd); ev_feed_fd_event(loop, fd->evfd, EV_WRITE); } - rlist_foreach_entry_reverse(fd, &swim_fd_opened, in_opened) { + rlist_foreach_entry_reverse(fd, &swim_fd_active, in_active) { if (!rlist_empty(&fd->recv_queue)) ev_feed_fd_event(loop, fd->evfd, EV_READ); } -- 2.17.2 (Apple Git-113)