xref: /openbsd-src/regress/lib/libpthread/setsockopt/2/setsockopt2.c (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1 /*	$OpenBSD: setsockopt2.c,v 1.1 2009/12/26 01:34:18 fgsch Exp $	*/
2 /*
3  * Federico G. Schwindt <fgsch@openbsd.org>, 2009. Public Domain.
4  */
5 
6 #include <sys/types.h>
7 #include <sys/socket.h>
8 #include <sys/wait.h>
9 #include <netinet/in.h>
10 #include <err.h>
11 #include <fcntl.h>
12 #include <netdb.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include "test.h"
17 
18 static void
19 alarm_handler(int sig)
20 {
21 	_exit(NOTOK);
22 }
23 
24 int
25 check_timeout(int s, int sec, struct timeval *to)
26 {
27 	struct timeval t1, t2;
28 	struct timeval e, d;
29 	char buf[BUFSIZ];
30 
31 	ASSERT(signal(SIGALRM, alarm_handler) != SIG_ERR);
32 	CHECKe(alarm(sec));
33 	CHECKe(gettimeofday(&t1, NULL));
34 	ASSERT(read(s, &buf, sizeof(buf)) == -1);
35 	CHECKe(gettimeofday(&t2, NULL));
36 	ASSERT(errno == EAGAIN);
37 	timersub(&t2, &t1, &e);
38 	timersub(&e, to, &d);
39 	return ((d.tv_sec > 1 || (d.tv_usec / 1000) > 100) ? 1 : 0);
40 }
41 
42 static void *
43 sock_connect(void *arg)
44 {
45 	struct sockaddr_in sin;
46 	struct timeval to;
47 	pid_t child_pid;
48 	int status;
49 	int s, s2, s3;
50 
51 	CHECKe(s = socket(AF_INET, SOCK_STREAM, 0));
52 	CHECKe(s2 = dup(s));
53 	CHECKe(s3 = fcntl(s, F_DUPFD, s));
54 	bzero(&sin, sizeof(sin));
55 	sin.sin_family = AF_INET;
56 	sin.sin_len = sizeof(sin);
57 	sin.sin_port = htons(6543);
58 	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
59 	CHECKe(connect(s, (struct sockaddr *)&sin, sizeof(sin)));
60 	to.tv_sec = 2;
61 	to.tv_usec = 0.5 * 1e6;
62 	CHECKe(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof(to)));
63 	CHECKe(child_pid = fork());
64 	if (child_pid == 0) {
65 		to.tv_sec = 1;
66 		to.tv_usec = 0.5 * 1e6;
67 		CHECKe(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof(to)));
68 		CHECKr(check_timeout(s, 2, &to));
69 		CHECKr(check_timeout(s2, 2, &to));
70 		CHECKr(check_timeout(s3, 2, &to));
71 		return (NULL);
72 	}
73 	sleep(2);
74 	CHECKr(check_timeout(s, 2, &to));
75 	CHECKr(check_timeout(s2, 2, &to));
76 	CHECKr(check_timeout(s3, 2, &to));
77 	CHECKe(s2 = dup(s));
78 	CHECKe(s3 = fcntl(s, F_DUPFD, s));
79 	CHECKr(check_timeout(s2, 2, &to));
80 	CHECKr(check_timeout(s3, 2, &to));
81 	CHECKe(close(s));
82 	CHECKe(close(s2));
83 	CHECKe(close(s3));
84 	ASSERTe(wait(&status), == child_pid);
85 	ASSERT(WIFEXITED(status));
86 	CHECKr(WEXITSTATUS(status));
87 	return (NULL);
88 }
89 
90 static void *
91 sock_accept(void *arg)
92 {
93 	pthread_t connect_thread;
94 	struct sockaddr_in sin;
95 	int s;
96 
97 	CHECKe(s = socket(AF_INET, SOCK_STREAM, 0));
98 	bzero(&sin, sizeof(sin));
99 	sin.sin_family = AF_INET;
100 	sin.sin_len = sizeof(sin);
101 	sin.sin_port = htons(6543);
102 	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
103 	CHECKe(bind(s, (struct sockaddr *)&sin, sizeof(sin)));
104 	CHECKe(listen(s, 2));
105 
106 	CHECKr(pthread_create(&connect_thread, NULL, sock_connect, NULL));
107 	CHECKr(pthread_join(connect_thread, NULL));
108 	return (NULL);
109 }
110 
111 int
112 main(int argc, char **argv)
113 {
114 	pthread_t accept_thread;
115 
116 	CHECKr(pthread_create(&accept_thread, NULL, sock_accept, NULL));
117 	CHECKr(pthread_join(accept_thread, NULL));
118 	SUCCEED;
119 }
120