Search code examples
linuxc++11thread-safetyfile-descriptor

Are pipe() and socket() thread safe? (double close() problem)


I'm using g++ (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
uname -a Linux ubuntu 4.18.0-17-generic #18~18.04.1-Ubuntu SMP Fri Mar 15 15:27:12 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

I thought all system calls that create file descriptors are thread safe on Linux. I mean, calling socket() and pipe() in parallel from different threads shouldn't return the same fd. Isn't it true?


Solution

  • It's not that fair because I didn't really show any real code, but I want to answer my own question to the sake of other users.

    • The symptoms I saw were errors like
      • errno 9 (Bad file descriptor)
      • Application dead lock (due to communication to other processes on bad file descriptors)
    • This is a multithreaded environment.
    • I started to had a doubts about socket() and pipe() to be not multithread safe due to logs I added in order to debug. I saw the same fd used by two different threads at the same time (I didn't put logs in all the relevant places, that's why I saw this strange occurance).
    • Thanks to this Double close() paragraph, I understood it was a variation of my problem:
      • Thread 1 open() fd 100
      • Thread 1 close() fd 100. Close #1 <--- this was the bug
      • Thread 2 open() fd 100 (totally fine now where 100 isn't used by any thread in the process)
      • Thread 1 close() again fd 100. Close #2.
        • This second close() actually closes fd 100 of Thread 2. Then when Thread 2 use this fd, it would get errno 9 (Bad file descriptor) for using a closed fd.
        • It may also get more complicated: in this moment fd 100 is closed. It may be re-opened by another thread which uses it with read()/write(). Thread 2 would use it as well with read()/write() - this scenario where two threads use the same fd is wrong and invalidates the data sent/received on that fd.