[CRIU] [PATCH v2 1/2] unix: Add support for restoring receive queue for unix DGRAM sockets

Kirill Tkhai ktkhai at odin.com
Thu Nov 26 09:54:40 PST 2015


Restore a receive queue in cases of:

1)socketpair with closed second end;
2)peer-less "listening" socket, who is a peer for others.

The only hack we use here is the connect with AF_UNSPEC family,
which clears peer of restoring socket. See unix_dgram_connect()
for the details.

This also makes socket_close_data test working.

Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>

v2: 1)Add a commentary near connect()
    2)Delete test/zdtm/live/static/socket_close_data.desc
---
 sk-unix.c                                    |   34 ++++++++++++++++++++++++++
 test/zdtm/live/static/socket_close_data.desc |    1 -
 2 files changed, 34 insertions(+), 1 deletion(-)
 delete mode 100644 test/zdtm/live/static/socket_close_data.desc

diff --git a/sk-unix.c b/sk-unix.c
index 91e4263..7ca4723 100644
--- a/sk-unix.c
+++ b/sk-unix.c
@@ -1133,6 +1133,40 @@ static int open_unixsk_standalone(struct unix_sk_info *ui)
 
 		close(sks[1]);
 		sk = sks[0];
+	} else if (ui->ue->type == SOCK_DGRAM && !ui->ue->peer) {
+		struct sockaddr_un addr;
+		int sks[2];
+
+		if (socketpair(PF_UNIX, ui->ue->type, 0, sks) < 0) {
+			pr_perror("Can't create socketpair");
+			return -1;
+		}
+
+		sk = sks[0];
+		addr.sun_family = AF_UNSPEC;
+
+		/*
+		 * socketpair() assigns sks[1] as a peer of sks[0]
+		 * (and vice versa). But in this case (not zero peer)
+		 * it's impossible for other sockets to connect
+		 * to sks[1] (see unix_dgram_connect()->unix_may_send()).
+		 * The below is hack: we use that connect with AF_UNSPEC
+		 * clears socket's peer.
+		 */
+		if (connect(sk, &addr, sizeof(addr.sun_family))) {
+			pr_perror("Can't clear socket's peer");
+			return -1;
+		}
+
+		/*
+		 * This must be after the connect() hack, because
+		 * connect() flushes receive queue.
+		 */
+		if (restore_sk_queue(sks[1], ui->ue->id)) {
+			pr_perror("Can't restore socket queue");
+			return -1;
+		}
+		close(sks[1]);
 	} else {
 		if (ui->ue->uflags & USK_CALLBACK) {
 			sk = run_plugins(RESTORE_UNIX_SK, ui->ue->ino);
diff --git a/test/zdtm/live/static/socket_close_data.desc b/test/zdtm/live/static/socket_close_data.desc
deleted file mode 100644
index 95c58b4..0000000
--- a/test/zdtm/live/static/socket_close_data.desc
+++ /dev/null
@@ -1 +0,0 @@
-{'flags': 'noauto'}



More information about the CRIU mailing list