1*eb897bf1Smvs /* $OpenBSD: unconacc.c,v 1.1 2021/12/10 00:50:18 mvs Exp $ */
2*eb897bf1Smvs
3*eb897bf1Smvs /*
4*eb897bf1Smvs * Copyright (c) 2021 Vitaliy Makkoveev <mvs@openbsd.org>
5*eb897bf1Smvs *
6*eb897bf1Smvs * Permission to use, copy, modify, and distribute this software for any
7*eb897bf1Smvs * purpose with or without fee is hereby granted, provided that the above
8*eb897bf1Smvs * copyright notice and this permission notice appear in all copies.
9*eb897bf1Smvs *
10*eb897bf1Smvs * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11*eb897bf1Smvs * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12*eb897bf1Smvs * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13*eb897bf1Smvs * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14*eb897bf1Smvs * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15*eb897bf1Smvs * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16*eb897bf1Smvs * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*eb897bf1Smvs */
18*eb897bf1Smvs
19*eb897bf1Smvs /*
20*eb897bf1Smvs * Provide multithreaded connect(2) and accept(2) stress test on
21*eb897bf1Smvs * unix(4) socket.
22*eb897bf1Smvs */
23*eb897bf1Smvs
24*eb897bf1Smvs #include <sys/types.h>
25*eb897bf1Smvs #include <sys/select.h>
26*eb897bf1Smvs #include <sys/socket.h>
27*eb897bf1Smvs #include <sys/stat.h>
28*eb897bf1Smvs #include <sys/sysctl.h>
29*eb897bf1Smvs #include <sys/un.h>
30*eb897bf1Smvs #include <stdarg.h>
31*eb897bf1Smvs #include <stdio.h>
32*eb897bf1Smvs #include <err.h>
33*eb897bf1Smvs #include <errno.h>
34*eb897bf1Smvs #include <pthread.h>
35*eb897bf1Smvs #include <string.h>
36*eb897bf1Smvs #include <time.h>
37*eb897bf1Smvs #include <unistd.h>
38*eb897bf1Smvs
39*eb897bf1Smvs static pthread_mutex_t therr_mtx = PTHREAD_MUTEX_INITIALIZER;
40*eb897bf1Smvs
41*eb897bf1Smvs static void
therr(int eval,const char * fmt,...)42*eb897bf1Smvs therr(int eval, const char *fmt, ...)
43*eb897bf1Smvs {
44*eb897bf1Smvs va_list ap;
45*eb897bf1Smvs
46*eb897bf1Smvs pthread_mutex_lock(&therr_mtx);
47*eb897bf1Smvs
48*eb897bf1Smvs va_start(ap, fmt);
49*eb897bf1Smvs verr(eval, fmt, ap);
50*eb897bf1Smvs va_end(ap);
51*eb897bf1Smvs }
52*eb897bf1Smvs
53*eb897bf1Smvs static void
therrc(int eval,int code,const char * fmt,...)54*eb897bf1Smvs therrc(int eval, int code, const char *fmt, ...)
55*eb897bf1Smvs {
56*eb897bf1Smvs va_list ap;
57*eb897bf1Smvs
58*eb897bf1Smvs pthread_mutex_lock(&therr_mtx);
59*eb897bf1Smvs
60*eb897bf1Smvs va_start(ap, fmt);
61*eb897bf1Smvs verrc(eval, code, fmt, ap);
62*eb897bf1Smvs va_end(ap);
63*eb897bf1Smvs }
64*eb897bf1Smvs
65*eb897bf1Smvs static void *
thr_acc(void * arg)66*eb897bf1Smvs thr_acc(void *arg)
67*eb897bf1Smvs {
68*eb897bf1Smvs int s = *(int *)arg;
69*eb897bf1Smvs
70*eb897bf1Smvs while (1) {
71*eb897bf1Smvs int n;
72*eb897bf1Smvs
73*eb897bf1Smvs if ((n = accept(s, NULL, NULL)) < 0) {
74*eb897bf1Smvs switch (errno) {
75*eb897bf1Smvs case EMFILE:
76*eb897bf1Smvs case ENFILE:
77*eb897bf1Smvs continue;
78*eb897bf1Smvs default:
79*eb897bf1Smvs therr(1, "accept");
80*eb897bf1Smvs }
81*eb897bf1Smvs }
82*eb897bf1Smvs
83*eb897bf1Smvs close(n);
84*eb897bf1Smvs }
85*eb897bf1Smvs
86*eb897bf1Smvs return NULL;
87*eb897bf1Smvs }
88*eb897bf1Smvs
89*eb897bf1Smvs static void *
thr_conn(void * arg)90*eb897bf1Smvs thr_conn(void *arg)
91*eb897bf1Smvs {
92*eb897bf1Smvs struct sockaddr_un *sun = arg;
93*eb897bf1Smvs int s;
94*eb897bf1Smvs
95*eb897bf1Smvs while (1) {
96*eb897bf1Smvs if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
97*eb897bf1Smvs switch (errno) {
98*eb897bf1Smvs case EMFILE:
99*eb897bf1Smvs case ENFILE:
100*eb897bf1Smvs case ENOBUFS:
101*eb897bf1Smvs continue;
102*eb897bf1Smvs default:
103*eb897bf1Smvs therr(1, "socket");
104*eb897bf1Smvs }
105*eb897bf1Smvs }
106*eb897bf1Smvs
107*eb897bf1Smvs if (connect(s, (struct sockaddr *)sun, sizeof(*sun)) < 0) {
108*eb897bf1Smvs switch (errno) {
109*eb897bf1Smvs case ECONNREFUSED:
110*eb897bf1Smvs continue;
111*eb897bf1Smvs default:
112*eb897bf1Smvs therr(1, "connect");
113*eb897bf1Smvs }
114*eb897bf1Smvs }
115*eb897bf1Smvs
116*eb897bf1Smvs close(s);
117*eb897bf1Smvs }
118*eb897bf1Smvs
119*eb897bf1Smvs return NULL;
120*eb897bf1Smvs }
121*eb897bf1Smvs
122*eb897bf1Smvs static struct sockaddr_un sun;
123*eb897bf1Smvs
124*eb897bf1Smvs int
main(int argc,char * argv[])125*eb897bf1Smvs main(int argc, char *argv[])
126*eb897bf1Smvs {
127*eb897bf1Smvs struct timespec testtime = {
128*eb897bf1Smvs .tv_sec = 60,
129*eb897bf1Smvs .tv_nsec = 0,
130*eb897bf1Smvs };
131*eb897bf1Smvs
132*eb897bf1Smvs int s;
133*eb897bf1Smvs
134*eb897bf1Smvs int mib[2], ncpu;
135*eb897bf1Smvs size_t len;
136*eb897bf1Smvs
137*eb897bf1Smvs int i;
138*eb897bf1Smvs
139*eb897bf1Smvs umask(0077);
140*eb897bf1Smvs
141*eb897bf1Smvs if (argc == 2 && !strcmp(argv[1], "--infinite"))
142*eb897bf1Smvs testtime.tv_sec = (10 * 365 * 86400);
143*eb897bf1Smvs
144*eb897bf1Smvs mib[0] = CTL_HW;
145*eb897bf1Smvs mib[1] = HW_NCPUONLINE;
146*eb897bf1Smvs len = sizeof(ncpu);
147*eb897bf1Smvs
148*eb897bf1Smvs if (sysctl(mib, 2, &ncpu, &len, NULL, 0) < 0)
149*eb897bf1Smvs err(1, "sysctl");
150*eb897bf1Smvs if (ncpu <= 0)
151*eb897bf1Smvs errx(1, "Wrong number of CPUs online: %d", ncpu);
152*eb897bf1Smvs
153*eb897bf1Smvs memset(&sun, 0, sizeof(sun));
154*eb897bf1Smvs sun.sun_len = sizeof(sun);
155*eb897bf1Smvs sun.sun_family = AF_UNIX;
156*eb897bf1Smvs snprintf(sun.sun_path, sizeof(sun.sun_path) - 1, "unconacc.socket");
157*eb897bf1Smvs
158*eb897bf1Smvs if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
159*eb897bf1Smvs err(1, "socket");
160*eb897bf1Smvs
161*eb897bf1Smvs unlink(sun.sun_path);
162*eb897bf1Smvs
163*eb897bf1Smvs if (bind(s, (struct sockaddr *)&sun, sizeof(sun)) < 0)
164*eb897bf1Smvs err(1, "bind");
165*eb897bf1Smvs if (listen(s, 10) < 0)
166*eb897bf1Smvs err(1, "listen");
167*eb897bf1Smvs
168*eb897bf1Smvs for (i = 0; i < (ncpu * 2); ++i) {
169*eb897bf1Smvs pthread_t thr;
170*eb897bf1Smvs int error;
171*eb897bf1Smvs
172*eb897bf1Smvs if ((error = pthread_create(&thr, NULL, thr_acc, &s)))
173*eb897bf1Smvs therrc(1, error, "pthread_create");
174*eb897bf1Smvs }
175*eb897bf1Smvs
176*eb897bf1Smvs for (i = 0; i < (ncpu * 2); ++i) {
177*eb897bf1Smvs pthread_t thr;
178*eb897bf1Smvs int error;
179*eb897bf1Smvs
180*eb897bf1Smvs if ((error = pthread_create(&thr, NULL, thr_conn, &sun)))
181*eb897bf1Smvs therrc(1, error, "pthread_create");
182*eb897bf1Smvs }
183*eb897bf1Smvs
184*eb897bf1Smvs nanosleep(&testtime, NULL);
185*eb897bf1Smvs
186*eb897bf1Smvs return 0;
187*eb897bf1Smvs }
188