Skip to content

socket may be non-blocking after Accept on macOS #25069

@wfurt

Description

@wfurt

This is rated to discussion from dotnet/corefx#23115

Consider following C code:

#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <sys/select.h>

int
main(int argc, char ** argv) {
    int ret, fd;
    struct sockaddr_in sa;
    socklen_t salen;
    int newfd;
    int flags;
    fd_set fs;

    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = INADDR_ANY;
    sa.sin_port = htons(6600);

    fd=socket(PF_INET,SOCK_STREAM, 0);

    if (argc > 1) {
        printf("setting accepting fd to non-block\n");
        ret=fcntl(fd, F_SETFL, O_NONBLOCK);
        fprintf(stderr, "Flags set on %d with %d\n", fd, ret);
    }

    if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) != 0) {
         fprintf(stderr, "Bind failed %s\n",strerror(errno));
         return -1;
    }
    if (listen(fd, 100) != 0) {
        fprintf(stderr, "Listen failed: %s\n", strerror(errno));
        return(1);
    }
    flags = fcntl(fd, F_GETFL);
    printf("Accepting fd %d flags=0x%x NONBLOCK=%d\n", fd, flags, flags & O_NONBLOCK );
    FD_ZERO(&fs);
    FD_SET(fd, &fs);
    select(fd+1, &fs, NULL, NULL, NULL);
    newfd = accept(fd, (struct sockaddr *)&sa, &salen);
    printf("newfd=%d\n", newfd);
    flags = fcntl(newfd, F_GETFL);
    printf("newfd flags=0x%x NONBLOCK=%d\n", flags, flags & O_NONBLOCK);

}

This will listen on port 6600 and accept new connection. It will printf socket flags after new socket is accepted. (nc 127.0.0.1 6600) When argument is passed to executable it will accept using non-blocking socket.

furt@Ubuntu:/tmp$ ./socket
Accepting fd 3 flags=0x2 NONBLOCK=0
newfd=4
newfd flags=0x2 NONBLOCK=0

furt@Ubuntu:/tmp$ ./socket -b
setting accepting fd to non-block
Accepting fd 3 flags=0x802 NONBLOCK=2048
newfd=4
newfd flags=0x2 NONBLOCK=0

however on macOS 10.12.6

Accepting fd 3 flags=0x2 NONBLOCK=0
newfd=4
newfd flags=0x2 NONBLOCK=0

macik:~ furt$ ./socket -b
setting accepting fd to non-block
Flags set on 3 with 0
Accepting fd 3 flags=0x6 NONBLOCK=4
newfd=4
newfd flags=0x6 NONBLOCK=4

I got same result on macOS 10.13 (High Sierra)
For comparison on FreeBSD 11.0:

[furt@toweinfu-d11 /tmp]$ ./socket -b
setting accepting fd to non-block
Flags set on 3 with 0
Accepting fd 3 flags=0x6 NONBLOCK=4
newfd=4
newfd flags=0x6 NONBLOCK=4

It seems like on macOS and BSD new socket inherits flags from accepting socket.

Metadata

Metadata

Assignees

Labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions