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

1

7

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, ..)
        ...
    }
}
Aymer answered 30/3, 2016 at 15:5 Comment(7)
How do you plan to use multiple threads? One per connection? A single connection shared between threads? Some other way?Converse
And generally, if the Opengroup reference doesn't explicitly say something is thread-safe, you should consider it unsafe.Converse
yes, single connection shared between two threads.Aymer
reading and writing on two parallel thread, and calling select also on two parallel thread. In 1st thread calling select with readfd and in another thread calling select with same fd on writefd.Aymer
@JoachimPileborg, wrong. It is thread-safe to call send/recv on the same socket from multiple threads (though not neccessarily guranteed to produce meaningful results for stream sockets) - still 100% thread safe.Caviar
@rajaashok: what you describe (reading from the socket in one thread, writing to the same socket in another thread) is perfectly thread-safe. A socket has separate buffers for reading and writing.Macmullin
@JoachimPileborg There are no shared buffers in this code. If you're referring to the socket send and receive buffers, they're in the kernel and protected by normal system call atomicity.Anywise
J
3

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.

Joletta answered 31/3, 2016 at 8:58 Comment(2)
"All functions defined by this volume of POSIX.1-2008 shall be thread-safe" - I think this says non reentrant functions (localtime, gmtime etc) are not thread safe, as it returns static variable address. But its not saying the APIs in sys/socket.h is thread safe even if we call with same fd.Aymer
socket functions are notably thread-safe even if called on the same fd. What's true is that it's not recommended to let many threads write/read to/from the same socket because it will lead to unreliable behaviour/unportable code (for example because send()/recv() are not guaranteed to send/recv the amount of data that has been specified - that's why letting one thread to read, one to write is correct), but all the calls not in the list are requested to be thread-safe to the implementers. socket functions included even if on the same fd.Joletta

© 2022 - 2024 — McMap. All rights reserved.