Skip to content

Commit 393d070

Browse files
mmhalPaolo Abeni
authored andcommitted
vsock/test: Add test for an unexpectedly lingering close()
There was an issue with SO_LINGER: instead of blocking until all queued messages for the socket have been successfully sent (or the linger timeout has been reached), close() would block until packets were handled by the peer. Add a test to alert on close() lingering when it should not. Signed-off-by: Michal Luczaj <[email protected]> Reviewed-by: Stefano Garzarella <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
1 parent 8b07b7e commit 393d070

File tree

1 file changed

+52
-0
lines changed

1 file changed

+52
-0
lines changed

tools/testing/vsock/vsock_test.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1839,6 +1839,53 @@ static void test_stream_linger_server(const struct test_opts *opts)
18391839
close(fd);
18401840
}
18411841

1842+
/* Half of the default to not risk timing out the control channel */
1843+
#define LINGER_TIMEOUT (TIMEOUT / 2)
1844+
1845+
static void test_stream_nolinger_client(const struct test_opts *opts)
1846+
{
1847+
bool waited;
1848+
time_t ns;
1849+
int fd;
1850+
1851+
fd = vsock_stream_connect(opts->peer_cid, opts->peer_port);
1852+
if (fd < 0) {
1853+
perror("connect");
1854+
exit(EXIT_FAILURE);
1855+
}
1856+
1857+
enable_so_linger(fd, LINGER_TIMEOUT);
1858+
send_byte(fd, 1, 0); /* Left unread to expose incorrect behaviour. */
1859+
waited = vsock_wait_sent(fd);
1860+
1861+
ns = current_nsec();
1862+
close(fd);
1863+
ns = current_nsec() - ns;
1864+
1865+
if (!waited) {
1866+
fprintf(stderr, "Test skipped, SIOCOUTQ not supported.\n");
1867+
} else if (DIV_ROUND_UP(ns, NSEC_PER_SEC) >= LINGER_TIMEOUT) {
1868+
fprintf(stderr, "Unexpected lingering\n");
1869+
exit(EXIT_FAILURE);
1870+
}
1871+
1872+
control_writeln("DONE");
1873+
}
1874+
1875+
static void test_stream_nolinger_server(const struct test_opts *opts)
1876+
{
1877+
int fd;
1878+
1879+
fd = vsock_stream_accept(VMADDR_CID_ANY, opts->peer_port, NULL);
1880+
if (fd < 0) {
1881+
perror("accept");
1882+
exit(EXIT_FAILURE);
1883+
}
1884+
1885+
control_expectln("DONE");
1886+
close(fd);
1887+
}
1888+
18421889
static struct test_case test_cases[] = {
18431890
{
18441891
.name = "SOCK_STREAM connection reset",
@@ -1999,6 +2046,11 @@ static struct test_case test_cases[] = {
19992046
.run_client = test_stream_linger_client,
20002047
.run_server = test_stream_linger_server,
20012048
},
2049+
{
2050+
.name = "SOCK_STREAM SO_LINGER close() on unread",
2051+
.run_client = test_stream_nolinger_client,
2052+
.run_server = test_stream_nolinger_server,
2053+
},
20022054
{},
20032055
};
20042056

0 commit comments

Comments
 (0)