dimanche 23 juin 2019

Are pipe() and socket() thread safe?

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?

I ran the following program and saw I get the same fd from pipe() and socket().

This is my source:

#include <iostream>
#include <thread>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

int p[2] = {};
int s;
int pRunning = true;
int sRunning = true;
int pI = 0;
int sI = 0;

int main() {
    std::thread pipeTrd([](){
        while (sRunning) {
            if (pipe(p) < 0) {
                printf("pipe() %d %s\n", errno, strerror(errno));
                break;
            }
            if ((p[0] == s) || (p[1] == s)) {
                printf("pipe() p[0] %d, p[1] %d, s %d\n", p[0], p[1], s);
                break;
            }
            close(p[0]);
            close(p[1]);
            pI++;
        }
        pRunning = false;
        return 0;
    });
    std::thread sockTrd([](){
        while (pRunning) {
            if ((s = socket(PF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0)) < 0) {
                printf("socket() %d %s\n", errno, strerror(errno));
                break;
            }
            if ((p[0] == s) || (p[1] == s)) {
                printf("socket() p[0] %d, p[1] %d, s %d\n", p[0], p[1], s);
                break;
            }
            close(s);
            sI++;
        }
        sRunning = false;
        return 0;
    });

    pipeTrd.join();
    sockTrd.join();
    printf("Pipe #%d, Socket #%d\n", pI, sI);
    return 0;
}

These are the outputs:

me@ubuntu:~/test$ ./socket_pipe_thread_safe 
pipe() p[0] 3, p[1] 4, s 3
Pipe #30, Socket #86
me@ubuntu:~/test$ ./socket_pipe_thread_safe 
pipe() p[0] 3, p[1] 4, s 3
Pipe #3, Socket #47
me@ubuntu:~/test$ ./socket_pipe_thread_safe 
pipe() p[0] 3, p[1] 4, s 3
Pipe #13, Socket #12

Aucun commentaire:

Enregistrer un commentaire