NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: kern/54650: Calling accept() with a non-blocking listening socket, returns a non-blocking connected socket, which is incorrect behaviour



The following reply was made to PR kern/54650; it has been noted by GNATS.

From: Sad Clouds <cryintothebluesky%gmail.com@localhost>
To: gnats-bugs%netbsd.org@localhost
Cc: gnats-admin%netbsd.org@localhost
Subject: Re: kern/54650: Calling accept() with a non-blocking listening
 socket, returns a non-blocking connected socket, which is incorrect
 behaviour
Date: Sat, 26 Oct 2019 22:51:45 +0100

 This is a multi-part message in MIME format.
 
 --Multipart=_Sat__26_Oct_2019_22_51_45_+0100_yuQIk.oe0XeU2Ov6
 Content-Type: text/plain; charset=US-ASCII
 Content-Transfer-Encoding: 7bit
 
 Attached is a test program, this is the output I get on Linux and NetBSD
 
 On Linux:
 $ ./a.out
 Create server thread
 Create client thread
 Accept connection, fd=5, addr=127.0.0.1, port=47746
 Connected socket is blocking
 
 On NetBSD:
 $ ./a.out
 Create server thread
 Create client thread
 Accept connection, fd=5, addr=127.0.0.1, port=65534
 Connected socket is non-blocking
 
 --Multipart=_Sat__26_Oct_2019_22_51_45_+0100_yuQIk.oe0XeU2Ov6
 Content-Type: text/x-csrc;
  name="test.c"
 Content-Disposition: attachment;
  filename="test.c"
 Content-Transfer-Encoding: 7bit
 
 #include <errno.h>
 #include <fcntl.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <arpa/inet.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <unistd.h>
 #include <pthread.h>
 #include <poll.h>
 
 #define ADDR "127.0.0.1"
 #define PORT 9999
 
 
 /* Set fd blocking or non-blocking */
 void set_fd_nonblock(int fd, bool set_flag)
 {
 	int ret_int, fcntl_flags;
 
 	/* Get current flags */
 	fcntl_flags = fcntl(fd, F_GETFL, 0);
 	if (fcntl_flags == -1)
 	{
 		fprintf(stderr, "Error %s:%d: fcntl() with F_GETFL failed, %s\n",
 			__FILE__, __LINE__, strerror(errno));
 		exit(EXIT_FAILURE);
 	}
 
 	if (set_flag)
 	{
 		/* Set non-blocking */
 		fcntl_flags |= O_NONBLOCK;
 	}
 	else
 	{
 		/* Set blocking */
 		fcntl_flags &= ~O_NONBLOCK;
 	}
 
 	ret_int = fcntl(fd, F_SETFL, fcntl_flags);
 	if (ret_int == -1)
 	{
 		fprintf(stderr, "Error %s:%d: fcntl() with F_SETFL failed, %s\n",
 			__FILE__, __LINE__, strerror(errno));
 		exit(EXIT_FAILURE);
 	}
 }
 
 /* Check fd is non-blocking */
 bool is_fd_nonblock(int fd)
 {
 	int fcntl_flags;
 
 	/* Get current flags */
 	fcntl_flags = fcntl(fd, F_GETFL, 0);
 	if (fcntl_flags == -1)
 	{
 		fprintf(stderr, "Error %s:%d: fcntl() with F_GETFL failed, %s\n",
 			__FILE__, __LINE__, strerror(errno));
 		exit(EXIT_FAILURE);
 	}
 
 	return (fcntl_flags & O_NONBLOCK);
 }
 
 
 /* Client thread */
 static void *cli(void *arg)
 {
 	struct sockaddr_in addr;
 	int conn_fd;
 
 	memset(&addr, 0, sizeof(addr));
 	if (inet_pton(AF_INET, ADDR, &(addr.sin_addr)) != 1)
 	{
 		fprintf(stderr, "Error %s:%d: inet_pton() failed, %s\n", __FILE__, __LINE__, strerror(errno));
 		exit(EXIT_FAILURE);
 	}
 	addr.sin_family = AF_INET;
 	addr.sin_port = htons(PORT);
 
 	conn_fd = socket(AF_INET, SOCK_STREAM, 0);
 	if (conn_fd < 0)
 	{
 		fprintf(stderr, "Error %s:%d: socket() failed, %s\n", __FILE__, __LINE__, strerror(errno));
 		exit(EXIT_FAILURE);
 	}
 
 	if (connect(conn_fd, (struct sockaddr *)&addr, sizeof(addr)) != 0)
 	{
 		fprintf(stderr, "Error %s:%d: connect() failed, %s\n", __FILE__, __LINE__, strerror(errno));
 		exit(EXIT_FAILURE);
 	}
 
 	return NULL;
 }
 
 /* Server thread */
 static void *srv(void *arg)
 {
 	struct sockaddr_in addr, cli_addr;
 	socklen_t cli_addr_len;
 	char addr_str[INET6_ADDRSTRLEN];
 	int ret_int, listen_fd, conn_fd;
 	ssize_t ret_ssize;
 	struct pollfd pollfd_array[1];
 
 	memset(&addr, 0, sizeof(addr));
 	addr.sin_family = AF_INET;
 	addr.sin_addr.s_addr = htonl(INADDR_ANY);
 	addr.sin_port = htons(PORT);
 
 	/* The usual - socket, bind, listen */
 	listen_fd = socket(AF_INET, SOCK_STREAM, 0);
 	if (listen_fd < 0)
 	{
 		fprintf(stderr, "Error %s:%d: socket() failed, %s\n", __FILE__, __LINE__, strerror(errno));
 		exit(EXIT_FAILURE);
 	}
 	if (bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
 	{
 		fprintf(stderr, "Error %s:%d: bind() failed, %s\n", __FILE__, __LINE__, strerror(errno));
 		exit(EXIT_FAILURE);
 	}
 	if (listen(listen_fd, 128) < 0)
 	{
 		fprintf(stderr, "Error %s:%d: listen() failed, %s\n", __FILE__, __LINE__, strerror(errno));
 		exit(EXIT_FAILURE);
 	}
 
 	/* Set listening socket non-blocking */
 	set_fd_nonblock(listen_fd, true);
 
 	/* Set poll events */
 	pollfd_array[0].fd = listen_fd;
 	pollfd_array[0].events = (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI);
 
 	/* Block in poll until socket is ready for I/O */
 	ret_int = poll(pollfd_array, 1, -1);
 	if (ret_int < 0)
 	{
 		fprintf(stderr, "Error %s:%d: poll() failed, %s\n", __FILE__, __LINE__, strerror(errno));
 		exit(EXIT_FAILURE);
 	}
 
 	/* Accept new connection */
 	cli_addr_len = sizeof(cli_addr);
 	conn_fd = accept(listen_fd, (struct sockaddr *)&cli_addr, &cli_addr_len);
 	if (conn_fd < 0)
 	{
 			fprintf(stderr, "Error %s:%d: accept() failed, %s\n", __FILE__, __LINE__, strerror(errno));
 			exit(EXIT_FAILURE);
 	}
 
 	if (inet_ntop(AF_INET, &(cli_addr.sin_addr), addr_str, sizeof(addr_str)) == NULL)
 	{
 		fprintf(stderr, "Error %s:%d: inet_ntop() failed, %s\n", __FILE__, __LINE__, strerror(errno));
 		exit(EXIT_FAILURE);
 	}
 	fprintf(stdout, "Accept connection, fd=%d, addr=%s, port=%hu\n",
 			conn_fd, addr_str, ntohs(cli_addr.sin_port));
 
 	/* Check if connected socket is non-blocking or blocking */
 	if (is_fd_nonblock(conn_fd))
 	{
 		fprintf(stdout, "Connected socket is non-blocking\n");
 	}
 	else
 	{
 		fprintf(stdout, "Connected socket is blocking\n");
 	}
 
 	return NULL;
 }
 
 
 int main(void)
 {
 	int ret_int;
 	pthread_t cli_tid, srv_tid;
 
 	fprintf(stdout, "Create server thread\n");
 	ret_int = pthread_create(&srv_tid, NULL, &srv, NULL);
 	if (ret_int != 0)
 	{
 		fprintf(stderr, "Error %s:%d: pthread_create() failed, %s\n", __FILE__, __LINE__, strerror(ret_int));
 		exit(EXIT_FAILURE);
 	}
 
 	sleep(1); /* Give server thread time to setup listening socket */
 
 	fprintf(stdout, "Create client thread\n");
 	ret_int = pthread_create(&cli_tid, NULL, &cli, NULL);
 	if (ret_int != 0)
 	{
 		fprintf(stderr, "Error %s:%d: pthread_create() failed, %s\n", __FILE__, __LINE__, strerror(ret_int));
 		exit(EXIT_FAILURE);
 	}
 
 
 	/* Wait for client to exit */
 	ret_int = pthread_join(cli_tid, NULL);
 	if (ret_int != 0)
 	{
 		fprintf(stderr, "Error %s:%d: pthread_join() failed, %s\n", __FILE__, __LINE__, strerror(ret_int));
 		exit(EXIT_FAILURE);
 	}
 
 	/* Wait for server to exit */
 	ret_int = pthread_join(srv_tid, NULL);
 	if (ret_int != 0)
 	{
 		fprintf(stderr, "Error %s:%d: pthread_join() failed, %s\n", __FILE__, __LINE__, strerror(ret_int));
 		exit(EXIT_FAILURE);
 	}
 
 }
 
 --Multipart=_Sat__26_Oct_2019_22_51_45_+0100_yuQIk.oe0XeU2Ov6--
 


Home | Main Index | Thread Index | Old Index