[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH] tst-cancel4: Make blocking on write more portable
From: |
Adhemerval Zanella |
Subject: |
Re: [PATCH] tst-cancel4: Make blocking on write more portable |
Date: |
Tue, 7 Jul 2020 18:08:31 -0300 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.8.0 |
On 05/07/2020 15:11, Samuel Thibault wrote:
> diff --git a/nptl/tst-cancel4-common.h b/nptl/tst-cancel4-common.h
> index c8763cacba..f99785c4f2 100644
> --- a/nptl/tst-cancel4-common.h
> +++ b/nptl/tst-cancel4-common.h
> @@ -62,7 +62,7 @@ static pthread_barrier_t b2;
>
> #define WRITE_BUFFER_SIZE 16384
>
> -/* Set the send buffer of socket S to 1 byte so any send operation
> +/* Set the send buffer of socket S to 1 byte and fill it so any send
> operation
> done with WRITE_BUFFER_SIZE bytes will force syscall blocking. */
> static void
> set_socket_buffer (int s)
> @@ -74,6 +74,23 @@ set_socket_buffer (int s)
> sizeof (val)) == 0);
> TEST_VERIFY_EXIT (getsockopt (s, SOL_SOCKET, SO_SNDBUF, &val, &len) == 0);
> TEST_VERIFY_EXIT (val < WRITE_BUFFER_SIZE);
> +
> + char buf = '\0';
> + struct timeval timeout = { .tv_sec = 0, .tv_usec = 0 };
> +
> + while (1)
> + {
> + fd_set set;
> + int ret;
> +
> + FD_ZERO (&set);
> + FD_SET (s, &set);
> + ret = select (s + 1, NULL, &set, NULL, &timeout);
> + if (!ret)
> + break;
> +
> + write (s, &buf, 1);
> + }
> }
Unfortunately this does not do what you are intending to do on Linux and
the tests only pass because of BZ#12683 where cancellation does not act on
write with side-effects.
For instance on kernel 5.4.0-40-generic the syscall sequence is:
[...]
select(4, NULL, [3], NULL, {tv_sec=0, tv_usec=0}) = 1 (out [3], left {tv_sec=0,
tv_usec=0})
write(3, "\0", 1) = 1
select(4, NULL, [3], NULL, {tv_sec=0, tv_usec=0}) = 1 (out [3], left {tv_sec=0,
tv_usec=0})
write(3, "\0", 1) = 1
select(4, NULL, [3], NULL, {tv_sec=0, tv_usec=0}) = 0 (Timeout)
[...]
clone(child_stack=0x7fd3ee4f4fb0,
flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTIDstrace:
Process 2641554 attached
, parent_tid=[2641554], tls=0x7fd3ee4f5700, child_tidptr=0x7fd3ee4f59d0) =
2641554
[...]
[pid 2641554] write(3,
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 16384
<unfinished ...>
[...]
[pid 2641553] tgkill(2641553, 2641554, SIGRTMIN) = 0
[pid 2641554] write(1, "write (3, buf, 16384) returned 2"..., 40write (3, buf,
16384) returned 2240 (0)
[...]
So it only fills 2 bytes on the socket buffer, but later the write *does*
return with side-effects indicating that it has at least written 2240 bytes.
I haven't investigate further on Linux kernel the iteration between
SOL_SOCKET, buffer filling and blocking operations. But it does show that
is indeed system specific and partial write might still occur even with
clever tricks. I am also not sure if this is something specific to
socketpair and if using a named socket might have different results.
Are you trying to make the tests behave better on Hurd? If so, in how
exactly Hurd behaves different than Linux in this case?