我在这里有一段服务器代码,可以在我的机器上正常运行,但是在我的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。