xref: /haiku/src/tests/system/network/firefox_crash.cpp (revision 5e54f6d4f9dd607ae2afcea4fe72f2f1763e4b5e)
1*5e54f6d4SAugustin Cavalier /*
2*5e54f6d4SAugustin Cavalier  * Copyright 2009, Axel Dörfler, axeld@pinc-software.de.
3*5e54f6d4SAugustin Cavalier  * Distributed under the terms of the MIT License.
4*5e54f6d4SAugustin Cavalier  */
5*5e54f6d4SAugustin Cavalier 
6*5e54f6d4SAugustin Cavalier //!	A test app trying to reproduce bug #2197.
7*5e54f6d4SAugustin Cavalier 
8*5e54f6d4SAugustin Cavalier #include <errno.h>
9*5e54f6d4SAugustin Cavalier #include <fcntl.h>
10*5e54f6d4SAugustin Cavalier #include <netinet/in.h>
11*5e54f6d4SAugustin Cavalier #include <stdio.h>
12*5e54f6d4SAugustin Cavalier #include <stdlib.h>
13*5e54f6d4SAugustin Cavalier #include <string.h>
14*5e54f6d4SAugustin Cavalier #include <sys/select.h>
15*5e54f6d4SAugustin Cavalier #include <sys/socket.h>
16*5e54f6d4SAugustin Cavalier 
17*5e54f6d4SAugustin Cavalier 
18*5e54f6d4SAugustin Cavalier static int
open_tcp_socket()19*5e54f6d4SAugustin Cavalier open_tcp_socket()
20*5e54f6d4SAugustin Cavalier {
21*5e54f6d4SAugustin Cavalier 	int fd = socket(AF_INET, SOCK_STREAM, 0);
22*5e54f6d4SAugustin Cavalier 	if (fd < 0)
23*5e54f6d4SAugustin Cavalier 		return -1;
24*5e54f6d4SAugustin Cavalier 
25*5e54f6d4SAugustin Cavalier 	// make it non-blocking
26*5e54f6d4SAugustin Cavalier 	fcntl(fd, F_SETFL, O_NONBLOCK);
27*5e54f6d4SAugustin Cavalier 
28*5e54f6d4SAugustin Cavalier 	return fd;
29*5e54f6d4SAugustin Cavalier }
30*5e54f6d4SAugustin Cavalier 
31*5e54f6d4SAugustin Cavalier 
32*5e54f6d4SAugustin Cavalier static void
init_sockaddr(struct sockaddr_in & address,unsigned ipAddress,unsigned port)33*5e54f6d4SAugustin Cavalier init_sockaddr(struct sockaddr_in& address, unsigned ipAddress, unsigned port)
34*5e54f6d4SAugustin Cavalier {
35*5e54f6d4SAugustin Cavalier 	memset(&address, 0, sizeof(sockaddr_in));
36*5e54f6d4SAugustin Cavalier 	address.sin_family = AF_INET;
37*5e54f6d4SAugustin Cavalier 	address.sin_port = htons(port);
38*5e54f6d4SAugustin Cavalier 	address.sin_addr.s_addr = htonl(ipAddress);
39*5e54f6d4SAugustin Cavalier }
40*5e54f6d4SAugustin Cavalier 
41*5e54f6d4SAugustin Cavalier 
42*5e54f6d4SAugustin Cavalier static int
tcp_pair(int pair[])43*5e54f6d4SAugustin Cavalier tcp_pair(int pair[])
44*5e54f6d4SAugustin Cavalier {
45*5e54f6d4SAugustin Cavalier 	pair[0] = pair[1] = -1;
46*5e54f6d4SAugustin Cavalier 
47*5e54f6d4SAugustin Cavalier 	int listenSocket = open_tcp_socket();
48*5e54f6d4SAugustin Cavalier 	if (listenSocket < 0)
49*5e54f6d4SAugustin Cavalier 		return -1;
50*5e54f6d4SAugustin Cavalier 
51*5e54f6d4SAugustin Cavalier 	sockaddr_in listenAddress;
52*5e54f6d4SAugustin Cavalier 	sockaddr_in peerAddress;
53*5e54f6d4SAugustin Cavalier 	sockaddr_in address;
54*5e54f6d4SAugustin Cavalier 	socklen_t length;
55*5e54f6d4SAugustin Cavalier 	init_sockaddr(listenAddress, INADDR_LOOPBACK, 0);
56*5e54f6d4SAugustin Cavalier 
57*5e54f6d4SAugustin Cavalier 	if (bind(listenSocket, (sockaddr*)&listenAddress, sizeof(sockaddr_in)) != 0)
58*5e54f6d4SAugustin Cavalier 		goto error;
59*5e54f6d4SAugustin Cavalier 
60*5e54f6d4SAugustin Cavalier 	length = sizeof(sockaddr_in);
61*5e54f6d4SAugustin Cavalier 	if (getsockname(listenSocket, (sockaddr*)&listenAddress, &length) != 0)
62*5e54f6d4SAugustin Cavalier 		goto error;
63*5e54f6d4SAugustin Cavalier 
64*5e54f6d4SAugustin Cavalier 	if (listen(listenSocket, 5) != 0)
65*5e54f6d4SAugustin Cavalier 		goto error;
66*5e54f6d4SAugustin Cavalier 
67*5e54f6d4SAugustin Cavalier 	pair[0] = open_tcp_socket();
68*5e54f6d4SAugustin Cavalier 	if (pair[0] < 0)
69*5e54f6d4SAugustin Cavalier 		goto error;
70*5e54f6d4SAugustin Cavalier 
71*5e54f6d4SAugustin Cavalier 	init_sockaddr(address, INADDR_LOOPBACK, ntohs(listenAddress.sin_port));
72*5e54f6d4SAugustin Cavalier 
73*5e54f6d4SAugustin Cavalier 	if (connect(pair[0], (sockaddr*)&address, sizeof(sockaddr_in)) != 0
74*5e54f6d4SAugustin Cavalier 		&& errno != EINPROGRESS)
75*5e54f6d4SAugustin Cavalier 		goto error;
76*5e54f6d4SAugustin Cavalier 
77*5e54f6d4SAugustin Cavalier 	if (errno == EINPROGRESS) {
78*5e54f6d4SAugustin Cavalier 		struct timeval tv;
79*5e54f6d4SAugustin Cavalier 		tv.tv_sec = 100000;
80*5e54f6d4SAugustin Cavalier 		tv.tv_usec = 0;
81*5e54f6d4SAugustin Cavalier 		fd_set set;
82*5e54f6d4SAugustin Cavalier 		FD_ZERO(&set);
83*5e54f6d4SAugustin Cavalier 		FD_SET(pair[0], &set);
84*5e54f6d4SAugustin Cavalier 		if (select(pair[0] + 1, NULL, &set, NULL, &tv) < 0)
85*5e54f6d4SAugustin Cavalier 			fprintf(stderr, "write select() failed: %s\n", strerror(errno));
86*5e54f6d4SAugustin Cavalier 	}
87*5e54f6d4SAugustin Cavalier 
88*5e54f6d4SAugustin Cavalier 	length = sizeof(sockaddr_in);
89*5e54f6d4SAugustin Cavalier 	if (getsockname(pair[0], (sockaddr*)&address, &length) != 0)
90*5e54f6d4SAugustin Cavalier 		goto error;
91*5e54f6d4SAugustin Cavalier 
92*5e54f6d4SAugustin Cavalier 	while (true) {
93*5e54f6d4SAugustin Cavalier 		pair[1] = accept(listenSocket, (sockaddr*)&peerAddress, &length);
94*5e54f6d4SAugustin Cavalier 		if (pair[1] >= 0)
95*5e54f6d4SAugustin Cavalier 			break;
96*5e54f6d4SAugustin Cavalier 
97*5e54f6d4SAugustin Cavalier 		if (errno != EAGAIN && errno != EWOULDBLOCK && errno != ETIMEDOUT)
98*5e54f6d4SAugustin Cavalier 			goto error;
99*5e54f6d4SAugustin Cavalier 
100*5e54f6d4SAugustin Cavalier 		struct timeval tv;
101*5e54f6d4SAugustin Cavalier 		tv.tv_sec = 100000;
102*5e54f6d4SAugustin Cavalier 		tv.tv_usec = 0;
103*5e54f6d4SAugustin Cavalier 		fd_set set;
104*5e54f6d4SAugustin Cavalier 		FD_ZERO(&set);
105*5e54f6d4SAugustin Cavalier 		FD_SET(listenSocket, &set);
106*5e54f6d4SAugustin Cavalier 		if (select(listenSocket + 1, &set, NULL, NULL, &tv) < 0)
107*5e54f6d4SAugustin Cavalier 			fprintf(stderr, "read select() failed: %s\n", strerror(errno));
108*5e54f6d4SAugustin Cavalier 	}
109*5e54f6d4SAugustin Cavalier 
110*5e54f6d4SAugustin Cavalier 	if (peerAddress.sin_port != address.sin_port)
111*5e54f6d4SAugustin Cavalier 		goto error;
112*5e54f6d4SAugustin Cavalier 
113*5e54f6d4SAugustin Cavalier 	close(listenSocket);
114*5e54f6d4SAugustin Cavalier     return 0;
115*5e54f6d4SAugustin Cavalier 
116*5e54f6d4SAugustin Cavalier error:
117*5e54f6d4SAugustin Cavalier 	close(listenSocket);
118*5e54f6d4SAugustin Cavalier 	for (int i = 0; i < 2; i++) {
119*5e54f6d4SAugustin Cavalier 		if (pair[i] >= 0)
120*5e54f6d4SAugustin Cavalier 			close(pair[i]);
121*5e54f6d4SAugustin Cavalier 	}
122*5e54f6d4SAugustin Cavalier 
123*5e54f6d4SAugustin Cavalier     return -1;
124*5e54f6d4SAugustin Cavalier }
125*5e54f6d4SAugustin Cavalier 
126*5e54f6d4SAugustin Cavalier 
127*5e54f6d4SAugustin Cavalier int
main(int argc,char ** argv)128*5e54f6d4SAugustin Cavalier main(int argc, char** argv)
129*5e54f6d4SAugustin Cavalier {
130*5e54f6d4SAugustin Cavalier 	int pair[2];
131*5e54f6d4SAugustin Cavalier 	if (tcp_pair(pair) == 0) {
132*5e54f6d4SAugustin Cavalier 		close(pair[0]);
133*5e54f6d4SAugustin Cavalier 		close(pair[1]);
134*5e54f6d4SAugustin Cavalier 	} else
135*5e54f6d4SAugustin Cavalier 		fprintf(stderr, "pair failed: %s\n", strerror(errno));
136*5e54f6d4SAugustin Cavalier 	return 0;
137*5e54f6d4SAugustin Cavalier }
138*5e54f6d4SAugustin Cavalier 
139