Search code examples
clinuxsocketssocketcan

Do I need to 'select' to wait for write availability when writing a socket from multiple threads?


I have code that writes to the same socket with multiple threads, like this, on Linux, which seems to be working in my development tests (pseudo-ish code):

Mutex theSocketMutex = ...;
int theSocket = ...;

void Thread () {
    while (...) {
        ...
        lock(theSocketMutex); 
        write(theSocket, ...);
        unlock(theSocketMutex);
        ...
    }
}

It's important that a single socket be used by all of these threads for writing (it's actually a SocketCAN socket, and I need to avoid the overhead of duplicate incoming frame processing on multiple sockets - I have one socket, one read thread, and multiple write threads).

The intended behavior is for the write to wait if hardware send buffers are full (which would be a few microseconds at most) rather than failing; but I'm not sure if the SocketCAN driver does this, or if it's guaranteed behavior of sockets in general, etc.

So my question is: Is the above sufficient, or do I also need to wait for the socket to be available for writing, e.g.:

void Thread () {
    while (...) {
        ...
        lock(theSocketMutex); 
        if (select(theSocket+1, NULL, &fdsetWrite, NULL, &timeout) != 1)
            ...; // fail
        else
            write(theSocket, ...);
        unlock(theSocketMutex); 
        ...
    }
}

It is working fine for my testing but I am not 100% confident in my tests here.


Solution

  • All that the select call will tell you is that you can write at least one byte to the descriptor without write (or send) blocking. It's not needed for writing to a descriptor from multiple threads, only the lock is.