Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are parallel calls to send/recv on the same socket valid as per POSIX standard?

I am trying to understand the usage of socket APIs (recv, send, select, close, etc) on parallel threads. That means using one socket file descriptor on two parallel threads. I have gone through this question. But still I am not able to find any standard doc which explains the usage of socket APIs in multiple thread. Even opengroup man page is not telling anything about this.

I also want to know whether below listed parallel thread usage scenarios are valid in POSIX socket APIs

1) Calling recv and send in two parallel threads

int main_thread() {
    fd = do_connect(); //TCP or UDP
    spawn_thread(recv_thread, fd);
    spwan_thread(send_thread, fd);
    ...
}

int recv_thread(fd) {
    while(1) {
        recv(fd, ..)
        ...
    }
}

int send_thread(fd) {
    while(1) {
        send(fd, ..)
        ...
    }
}

2) Calling recv and send with select in two parallel threads

int recv_thread(fd) {
    while(1) {
        select(fd in readfd)
        recv(fd, ..)
        ...
    }
}

int send_thread(fd) {
    while(1) {
        select(fd in write)
        send(fd, ..)
        ...
    }
}

3) Calling recv and send with setsockopt, ioctl, fcntl in two paralle threads

int recv_thread(fd) {
    int flag = 1
    while(1) {
        ioctl(fd, FIONBIO, &flag); //enable non block
        recv(fd, ..)
        flag = 0;
        ioctl(fd, FIONBIO, &flag); //disable non block
        ...
    }
}

int send_thread(fd) {
    while(1) {
        select(fd in write)
        send(fd, ..)
        ...
    }
}
like image 787
rashok Avatar asked Oct 19 '22 12:10

rashok


1 Answers

Posix functions are thread-safe "by default":

2.9.1 Thread-Safety

All functions defined by this volume of POSIX.1-2008 shall be thread-safe, except that the following functions need not be thread-safe.

As many have already commented, you can safely call the mentioned calls from different threads.

Case "1" and "2" are quite typical (one thread receiving, one sending, each thread handling many connections with select()) for production code.

Case "3" is somehow odd, and probably source of troubles (it will work, the calls are valid, but it may be not straightforward to get the desired behaviour). Generally you either put the socket in non-blocking mode at the beginning and handle EAGAIN/EWOULDBLOCK errors in send()/recv() calls or blocking and use select()/pselect()/poll()/ppoll().

The sending thread in this case will randomly "find" the socket being in blocking or not-blocking mode: I wouldn't do that.

like image 185
Sigi Avatar answered Oct 29 '22 22:10

Sigi