[CRIU] [PATCH] unix: wait for listen() as well as bind()
Andrew Vagin
avagin at odin.com
Wed Jul 15 07:46:30 PDT 2015
On Wed, Jul 15, 2015 at 07:06:25AM -0600, Tycho Andersen wrote:
> We need to wait for listen() as well as bind() for internal unix sockets, or we
> can race like this:
>
> (00.135950) 1: Opening standalone socket (id 0xb ino 0x9422f peer 0)
> (00.135974) 353: Error (sk-unix.c:701): Can't connect 0x947c4 socket: Connection refused
> (00.136390) 1: Error (cr-restore.c:1228): 353 exited, status=1
> (00.136407) 1: Putting 0x9422f into listen state
>
> (where 0x9422f is the peer for 0x947c4)
>
> This race was pretty rare for me, but I've run 1000 tests and it didn't
> happen so hopefully this patch fixes it :)
>
Acked-by: Andrew Vagin <avagin at odin.com>
> Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
> ---
> sk-unix.c | 16 ++++++++++++----
> 1 file changed, 12 insertions(+), 4 deletions(-)
>
> diff --git a/sk-unix.c b/sk-unix.c
> index 2a4df85..6c9ec25 100644
> --- a/sk-unix.c
> +++ b/sk-unix.c
> @@ -631,7 +631,13 @@ struct unix_sk_info {
> unsigned flags;
> struct unix_sk_info *peer;
> struct file_desc d;
> - futex_t bound;
> +
> + /*
> + * Futex to signal when the socket is prepared. In particular, we
> + * signal after bind()ing the socket if it is not in TCP_LISTEN, or
> + * after listen() if the socket is in TCP_LISTEN.
> + */
> + futex_t prepared;
> };
>
> #define USK_PAIR_MASTER 0x1
> @@ -689,7 +695,7 @@ static int post_open_unix_sk(struct file_desc *d, int fd)
>
> /* Skip external sockets */
> if (!list_empty(&peer->d.fd_info_head))
> - futex_wait_while(&peer->bound, 0);
> + futex_wait_while(&peer->prepared, 0);
>
> memset(&addr, 0, sizeof(addr));
> addr.sun_family = AF_UNIX;
> @@ -764,7 +770,8 @@ static int bind_unix_sk(int sk, struct unix_sk_info *ui)
> }
> }
>
> - futex_set_and_wake(&ui->bound, 1);
> + if (ui->ue->state != TCP_LISTEN)
> + futex_set_and_wake(&ui->prepared, 1);
> done:
> return 0;
> }
> @@ -957,6 +964,7 @@ static int open_unixsk_standalone(struct unix_sk_info *ui)
> pr_perror("Can't make usk listen");
> return -1;
> }
> + futex_set_and_wake(&ui->prepared, 1);
> }
> out:
> if (rst_file_params(sk, ui->ue->fown, ui->ue->flags))
> @@ -1012,7 +1020,7 @@ static int collect_one_unixsk(void *o, ProtobufCMessage *base)
> } else
> ui->name = NULL;
>
> - futex_init(&ui->bound);
> + futex_init(&ui->prepared);
> ui->peer = NULL;
> ui->flags = 0;
> pr_info(" `- Got %#x peer %#x (name %s)\n",
> --
> 2.1.4
>
> _______________________________________________
> CRIU mailing list
> CRIU at openvz.org
> https://lists.openvz.org/mailman/listinfo/criu
More information about the CRIU
mailing list