View | Details | Raw Unified | Return to bug 212716 | Differences between
and this patch

Collapse All | Expand All

(-)b/tests/sys/kern/Makefile (+2 lines)
Lines 30-35 ATF_TESTS_C+= sigaltstack Link Here
30
ATF_TESTS_C+=	sigwait
30
ATF_TESTS_C+=	sigwait
31
ATF_TESTS_C+=	socket_accf
31
ATF_TESTS_C+=	socket_accf
32
ATF_TESTS_C+=	socket_msg_trunc
32
ATF_TESTS_C+=	socket_msg_trunc
33
ATF_TESTS_C+=	socket_msg_waitall
33
TEST_METADATA.sigwait+=	is_exclusive="true"
34
TEST_METADATA.sigwait+=	is_exclusive="true"
34
.if ${MACHINE_ARCH} != "i386" && ${MACHINE_ARCH:Mpowerpc*} == ""
35
.if ${MACHINE_ARCH} != "i386" && ${MACHINE_ARCH:Mpowerpc*} == ""
35
ATF_TESTS_C+=	subr_physmem_test
36
ATF_TESTS_C+=	subr_physmem_test
Lines 71-76 LIBADD.unix_seqpacket_test+= pthread Link Here
71
LIBADD.kcov+=				pthread
72
LIBADD.kcov+=				pthread
72
CFLAGS.ktls_test+=			-DOPENSSL_API_COMPAT=0x10100000L
73
CFLAGS.ktls_test+=			-DOPENSSL_API_COMPAT=0x10100000L
73
LIBADD.ktls_test+=			crypto util
74
LIBADD.ktls_test+=			crypto util
75
LIBADD.socket_msg_waitall+=		pthread
74
LIBADD.sendfile_helper+=		pthread
76
LIBADD.sendfile_helper+=		pthread
75
LIBADD.fdgrowtable_test+=		util pthread kvm procstat
77
LIBADD.fdgrowtable_test+=		util pthread kvm procstat
76
LIBADD.sigwait+=			rt
78
LIBADD.sigwait+=			rt
(-)b/tests/sys/kern/socket_msg_waitall.c (+181 lines)
Added Link Here
1
/*-
2
 * SPDX-License-Identifier: BSD-2-Clause
3
 *
4
 * Copyright (c) 2023 The FreeBSD Foundation
5
 *
6
 * This software was developed by Mark Johnston under sponsorship from
7
 * the FreeBSD Foundation.
8
 */
9
10
#include <sys/types.h>
11
#include <sys/socket.h>
12
#include <sys/un.h>
13
14
#include <netinet/in.h>
15
16
#include <errno.h>
17
#include <pthread.h>
18
#include <stdlib.h>
19
#include <unistd.h>
20
21
#include <atf-c.h>
22
23
struct close_test_params {
24
	struct sockaddr_storage sa;
25
	size_t msglen;
26
	int count;
27
	int af, type, proto;
28
};
29
30
static void *
31
close_test_client(void *arg)
32
{
33
	struct close_test_params *p = arg;
34
	char *buf;
35
	size_t buflen;
36
37
	buflen = p->msglen + 1;
38
	buf = malloc(buflen);
39
	ATF_REQUIRE(buf != NULL);
40
41
	while (p->count-- > 0) {
42
		ssize_t n;
43
		int error, s;
44
45
		s = socket(p->af, p->type, p->proto);
46
		ATF_REQUIRE_MSG(s >= 0, "socket: %s", strerror(errno));
47
48
		error = connect(s, (struct sockaddr *)&p->sa, p->sa.ss_len);
49
		ATF_REQUIRE_MSG(error == 0, "connect: %s", strerror(errno));
50
51
		n = recv(s, buf, buflen, MSG_WAITALL);
52
		ATF_REQUIRE_MSG(n == (ssize_t)p->msglen,
53
		    "recv: %s", strerror(errno));
54
55
		ATF_REQUIRE(close(s) == 0);
56
	}
57
58
	return (NULL);
59
}
60
61
static void
62
close_test(struct sockaddr *sa, unsigned int count, int af, int type, int proto)
63
{
64
	struct close_test_params p;
65
	const char *msg;
66
	pthread_t t;
67
	size_t msglen;
68
	int error, s;
69
70
	s = socket(af, type, proto);
71
	ATF_REQUIRE_MSG(s >= 0, "socket %s", strerror(errno));
72
73
	ATF_REQUIRE_MSG(bind(s, sa, sa->sa_len) == 0,
74
	    "bind: %s", strerror(errno));
75
	ATF_REQUIRE_MSG(listen(s, 1) == 0,
76
	    "listen: %s", strerror(errno));
77
	ATF_REQUIRE_MSG(getsockname(s, sa, &(socklen_t){ sa->sa_len }) == 0,
78
	    "getsockname: %s", strerror(errno));
79
80
	msg = "hello bonjour";
81
	msglen = strlen(msg) + 1;
82
	p = (struct close_test_params){
83
		.count = count,
84
		.msglen = msglen,
85
		.af = af,
86
		.type = type,
87
		.proto = proto,
88
	};
89
	memcpy(&p.sa, sa, sa->sa_len);
90
	error = pthread_create(&t, NULL, close_test_client, &p);
91
	ATF_REQUIRE_MSG(error == 0, "pthread_create: %s", strerror(error));
92
93
	while (count-- > 0) {
94
		ssize_t n;
95
		int cs;
96
97
		cs = accept(s, NULL, NULL);
98
		ATF_REQUIRE_MSG(cs >= 0, "accept: %s", strerror(errno));
99
100
		n = send(cs, msg, msglen, 0);
101
		ATF_REQUIRE_MSG(n == (ssize_t)msglen,
102
		    "send: %s", strerror(errno));
103
104
		ATF_REQUIRE(close(cs) == 0);
105
	}
106
107
	ATF_REQUIRE(close(s) == 0);
108
	ATF_REQUIRE(pthread_join(t, NULL) == 0);
109
}
110
111
/*
112
 * Make sure that closing a connection kicks a MSG_WAITALL recv() out of the
113
 * syscall.  See bugzilla PR 212716.
114
 */
115
ATF_TC(close_tcp);
116
ATF_TC_HEAD(close_tcp, tc)
117
{
118
	atf_tc_set_md_var(tc, "timeout", "10");
119
}
120
ATF_TC_BODY(close_tcp, tc)
121
{
122
	struct sockaddr_in sin;
123
124
	sin = (struct sockaddr_in){
125
		.sin_len = sizeof(sin),
126
		.sin_family = AF_INET,
127
		.sin_addr = { htonl(INADDR_LOOPBACK) },
128
		.sin_port = htons(0),
129
	};
130
	close_test((struct sockaddr *)&sin, 1000, AF_INET, SOCK_STREAM,
131
	    IPPROTO_TCP);
132
}
133
134
/* A variant of the above test for UNIX domain stream sockets. */
135
ATF_TC(close_unix_stream);
136
ATF_TC_HEAD(close_unix_stream, tc)
137
{
138
	atf_tc_set_md_var(tc, "timeout", "10");
139
}
140
ATF_TC_BODY(close_unix_stream, tc)
141
{
142
	struct sockaddr_un sun;
143
144
	sun = (struct sockaddr_un){
145
		.sun_len = sizeof(sun),
146
		.sun_family = AF_UNIX,
147
		.sun_path = "socket_msg_waitall_unix",
148
	};
149
	close_test((struct sockaddr *)&sun, 1000, AF_UNIX, SOCK_STREAM, 0);
150
	ATF_REQUIRE_MSG(unlink(sun.sun_path) == 0,
151
	    "unlink: %s", strerror(errno));
152
}
153
154
/* A variant of the above test for UNIX domain seqpacket sockets. */
155
ATF_TC(close_unix_seqpacket);
156
ATF_TC_HEAD(close_unix_seqpacket, tc)
157
{
158
	atf_tc_set_md_var(tc, "timeout", "10");
159
}
160
ATF_TC_BODY(close_unix_seqpacket, tc)
161
{
162
	struct sockaddr_un sun;
163
164
	sun = (struct sockaddr_un){
165
		.sun_len = sizeof(sun),
166
		.sun_family = AF_UNIX,
167
		.sun_path = "socket_msg_waitall_unix",
168
	};
169
	close_test((struct sockaddr *)&sun, 1000, AF_UNIX, SOCK_SEQPACKET, 0);
170
	ATF_REQUIRE_MSG(unlink(sun.sun_path) == 0,
171
	    "unlink: %s", strerror(errno));
172
}
173
174
ATF_TP_ADD_TCS(tp)
175
{
176
	ATF_TP_ADD_TC(tp, close_tcp);
177
	ATF_TP_ADD_TC(tp, close_unix_stream);
178
	ATF_TP_ADD_TC(tp, close_unix_seqpacket);
179
180
	return (atf_no_error());
181
}

Return to bug 212716