L'envoi de descripteur de fichier Linux, le socket

J'essaie d'envoyer un fichier descripteur de linux, le socket, mais il ne fonctionne pas. Ce que je fais mal? Comment est-on censé debug quelque chose comme cela? J'ai essayé de mettre perror() partout où c'est possible, mais ils ont affirmé que tout est ok. Voici ce que j'ai écrit:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <fcntl.h>

void wyslij(int socket, int fd)  //send fd by socket
{
    struct msghdr msg = {0};

    char buf[CMSG_SPACE(sizeof fd)];

    msg.msg_control = buf;
    msg.msg_controllen = sizeof buf;

    struct cmsghdr * cmsg = CMSG_FIRSTHDR(&msg);
    cmsg->cmsg_level = SOL_SOCKET;
    cmsg->cmsg_type = SCM_RIGHTS;
    cmsg->cmsg_len = CMSG_LEN(sizeof fd);

    *((int *) CMSG_DATA(cmsg)) = fd;

    msg.msg_controllen = cmsg->cmsg_len;  //why does example from man need it? isn't it redundant?

    sendmsg(socket, &msg, 0);
}


int odbierz(int socket)  //receive fd from socket
{
    struct msghdr msg = {0};
    recvmsg(socket, &msg, 0);

    struct cmsghdr * cmsg = CMSG_FIRSTHDR(&msg);

    unsigned char * data = CMSG_DATA(cmsg);

    int fd = *((int*) data);  //here program stops, probably with segfault

    return fd;
}


int main()
{
    int sv[2];
    socketpair(AF_UNIX, SOCK_DGRAM, 0, sv);

    int pid = fork();
    if (pid > 0)  //in parent
    {
        close(sv[1]);
        int sock = sv[0];

        int fd = open("./z7.c", O_RDONLY);

        wyslij(sock, fd);

        close(fd);
    }
    else  //in child
    {
        close(sv[0]);
        int sock = sv[1];

        sleep(0.5);
        int fd = odbierz(sock);
    }

}
Je voulais dire CMSG_DATA je ne sais pas ce qu'ils sont, mais je pense que j'ai trouvé le problème.
Pourquoi êtes-vous en envoyant le valeur d'un descripteur de fichier sur une socket? Qu'est-ce que le récepteur censé faire avec elle? Si le récepteur n'est pas dans le même processus que l'expéditeur, le descripteur de fichier ne signifie rien pour le récepteur, comme un descripteur de fichier est spécifique au procédé. En tout cas, sur l'extrémité de réception, lors de l'utilisation de recvmsg(), vous avez besoin d'une boucle sur le message reçu en-têtes à la recherche pour le SOL_SOCKET/SCM_RIGHTS en-tête. Maintenant, vous êtes en supposant que chaque message commence par SCM_RIGHTS, et qui ne risque pas d'être toujours le cas.
Juste pour vérifier - vous êtes conscient qu'il est possible d'envoyer (utilisable) de descripteurs de fichiers entre les processus à l'aide de SCM_RIGHTS et AF_UNIX sockets?
Je retire mon commentaire au sujet de l'envoi de la valeur d'un descripteur de fichier dans les limites du processus étant non valide. Mais mon commentaire sur la nécessité de numériser correctement reçu recvmsg() en-têtes pour SCM_RIGHTS s'applique toujours.
FWIW, Il n'est pas spécifique à Linux (beaucoup, bien que je ne crois pas tout, Unix saveurs de soutien). Mais je suis d'accord que la numérisation de la recvmsg() des en-têtes est la meilleure pratique 🙂

OriginalL'auteur Dekakaruk | 2015-01-17