diff --git a/homa_sock.c b/homa_sock.c index bf3e743e..85c2c9b9 100644 --- a/homa_sock.c +++ b/homa_sock.c @@ -415,6 +415,12 @@ void homa_sock_destroy(struct sock *sk) if (!hsk->homa) return; + /* Normally homa_close has already done this, but not if socket + * creation failed after homa_socket (inet_create calls only + * sk_common_release). + */ + homa_sock_shutdown(hsk); + tt_record1("Starting to destroy socket %d", hsk->port); while (!list_empty(&hsk->dead_rpcs)) { #ifndef __STRIP__ /* See strip.py */ diff --git a/test/unit_homa_sock.c b/test/unit_homa_sock.c index be401480..a255fe0a 100644 --- a/test/unit_homa_sock.c +++ b/test/unit_homa_sock.c @@ -521,6 +521,21 @@ TEST_F(homa_sock, homa_sock_shutdown__wakeup_interests_and_wmem) unit_sock_destroy(&self->hsk); } +TEST_F(homa_sock, homa_sock_destroy__unlink_socket) +{ + struct homa_sock hsk; + int port; + + /* This is the path taken when inet_create fails after ->init + * (e.g. a cgroup BPF program rejects the socket): ->destroy runs + * without ->close. + */ + mock_sock_init(&hsk, self->hnet, 0); + port = hsk.port; + homa_sock_destroy(&hsk.sock); + EXPECT_EQ(NULL, homa_sock_find(self->hnet, port)); + EXPECT_EQ(NULL, hsk.slink); +} TEST_F(homa_sock, homa_sock_bind) { struct homa_sock hsk2;