Linux sendmsg返回带有良好文件的EBADF

时间:2019-01-29 02:59:46

标签: linux amazon-web-services network-programming

我在这里有一段服务器代码,可以在我的机器上正常运行,但是在我的Amazon EC2实例上出现EBADF失败。我了解Amazon Linux映像已经过大量修改,但我认为更可能是我自己犯了该错误。我正在尝试使用UNIX套接字将套接字从父实例传递给子实例。

这是代码,然后我将讨论我尝试过的内容。该代码对主服务器循环进行编码以侦听连接,接受连接并将套接字传递给另一个进程。

main.h

#define COUNT(array) sizeof array / sizeof array[0]
int id;
int server;
struct worker {
    int pid;
    int to;
};
struct worker *workers;
struct task {
    unsigned int client;
    struct sockaddr_in addr;
    socklen_t length;
};

main.c

void mainLoop() {
    INFO("Waiting for connections");
    struct task newTask;

    while(1) {
        if (++id >= NUM_WORKERS) {
            id = 0;
        }

        newTask.client = accept(server, (struct sockaddr *)&newTask.addr, &newTask.length);
        if (newTask.client < 0) {
            INFO("Accept failed with result %d and error (%d) '%s'", newTask.client, errno, strerror(errno));
            continue;
        }

        char buf[CMSG_SPACE(sizeof newTask.client)];
        struct iovec iov[] = {
            {&newTask, sizeof newTask}
        };
        struct msghdr msg = {
            NULL, 0,
            iov, COUNT(iov),
            buf, sizeof buf,
            0
        };

        struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
        cmsg->cmsg_level = SOL_SOCKET;
        cmsg->cmsg_type = SCM_RIGHTS;
        cmsg->cmsg_len = CMSG_LEN(sizeof newTask.client);
        *CMSG_DATA(cmsg) = newTask.client;
        msg.msg_controllen = cmsg->cmsg_len;

        int result = sendmsg(workers[id].to, &msg, MSG_DONTWAIT);
        if (result < 0) // result = -1 on my server
            INFO("sendmsg failed with %d: (%d) '%s'", result, errno, strerror(errno));
    }
}

worker [id] .to套接字是使用套接字对制作的,就像这样:

int sockets[2];
socketpair(AF_LOCAL, SOCK_STREAM, 0, sockets);

根据是否已定义调试,将INFO宏用于fprintf到信息日志或stdout,并在末尾添加换行符。

如果我删除控制消息部分并将buf设置为NULL(换句话说,不要传递套接字),则消息发送就很好了。另外,当我使用F_GETFL调用fnctl以获取所有涉及的套接字(服务器,worker [id] .to和newTask.client)的状态时,它们都返回状态2(O_RDWR)。再说一次,它可以在我的机器上运行,但不能在Amazon服务器上运行。

此代码看起来是错误的还是Amazon有错误?我还能尝试什么或如何调试呢?

服务器在Amazon EC2实例上运行CentOS 7。内核版本为4.19。我的本地计算机是具有相同内核的Debian Sid。

0 个答案:

没有答案