Call to accept() does not time out when setting SO_RCVTIMEO on a socket

Dimitri Staessens dimitri.staessens at intec.ugent.be
Thu Dec 8 12:43:57 UTC 2016


Dear devs,

I'm trying to get an accept() call to time out using setsockopt.

On Linux, the example below terminates:

[dstaesse at phoneutria]$ gcc accept_st.c -o accept_st
[dstaesse at phoneutria]$ ./accept_st
Timeout is 0:100000.
Check is 0:103333.
Accept returned: Resource temporarily unavailable.
Accept returned: Resource temporarily unavailable.
Accept returned: Resource temporarily unavailable.
Bye.

On FreeBSD 11.0-RELEASE however, it hangs on the accept() forever.

Is this a known issue?

Thanks for your help,

Dimitri

--- example source:

#define _POSIX_C_SOURCE 200809L

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

#include <sys/time.h>
#include <sys/socket.h>
#include <sys/un.h>

#define TIMEOUT 100 /* ms */
#define RUNNING 0
#define SHUTDOWN 1

#define FN "/tmp/accept_st_socket"

int sfd;

void main(void)
{
         int count = 0;
         int cfd;
         struct timeval tv = {(TIMEOUT / 1000), (TIMEOUT % 1000) * 1000};
         struct timeval check;
         socklen_t len = sizeof(check);
         struct sockaddr_un serv_addr;

         printf("Timeout is %lu:%lu.\n", tv.tv_sec, tv.tv_usec);

         sfd = socket(AF_UNIX, SOCK_STREAM, 0);
         if (sfd < 0) {
                 printf("Failed to open socket: %s.\n", strerror(errno));
                 exit(EXIT_FAILURE);
         }

         if (access(FN, F_OK) != -1) {
                 /* File exists */
                 if (unlink(FN))
                         exit(EXIT_FAILURE);
         }

         serv_addr.sun_family = AF_UNIX;
         sprintf(serv_addr.sun_path, "%s", FN);

         if (bind(sfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))) {
                 printf("Failed to bind socket: %s.\n", strerror(errno));
                 close(sfd);
                 exit(EXIT_FAILURE);
         }

         if (listen(sfd, 0)) {
                 printf("Failed to listen on socket: %s.\n", 
strerror(errno));
                 close(sfd);
                 exit(EXIT_FAILURE);
         }

         if (setsockopt(sfd, SOL_SOCKET, SO_RCVTIMEO, (void *) &tv, len))
                 printf("Failed to set timeout on socket: %s.\n",
                        strerror(errno));

         getsockopt(sfd, SOL_SOCKET, SO_RCVTIMEO, &check, &len);

         printf("Check is %lu:%lu.\n", check.tv_sec, check.tv_usec);

         while (count < 3) {
                 cfd = accept(sfd, 0, 0);
                 printf("Accept returned: %s.\n", strerror(errno));
                 ++count;
         }

         printf("Bye.\n");

         exit(EXIT_SUCCESS);
}


-- 
Dimitri Staessens
Ghent University - imec
Dept. of Information Technology (INTEC)
Internet Based Communication Networks and Services
Technologiepark 15
9052 Zwijnaarde
T: +32 9 331 48 70
F: +32 9 331 48 99



More information about the freebsd-bugs mailing list