sendmsg()无效参数(??)

时间:2012-02-21 00:29:32

标签: c linux ipc

首先是某些上下文:有一个主程序(一个Web服务器),它会分配一堆工作者,并等待传入​​的连接。当它接受一个时,它通过sendmsg()原语将套接字描述符发送给其中一个worker。

这是应该发送描述符的代码:

int send_msg (worker_t * l, struct message_t * m)
{
#ifdef __WIN32__

#else
     struct msghdr msg;                      
     struct cmsghdr * cmsg;                   
     char   anc [CMSG_SPACE (sizeof(int))]; 
     int *  fd_ptr;

     int    buf [1] = {m->msg};
     struct iovec vec;
     vec.iov_base = buf;
     vec.iov_len  = sizeof (int);

     msg.msg_iov = &vec;
     msg.msg_iovlen = 1;

     msg.msg_control = NULL;
     msg.msg_controllen = 0;

     if (m->msg == GC_SOCKET) {
          msg.msg_control = anc;
          msg.msg_controllen = sizeof anc;

          cmsg = CMSG_FIRSTHDR (&msg);
          cmsg->cmsg_level = SOL_SOCKET;
          cmsg->cmsg_type = SCM_RIGHTS;
          cmsg->cmsg_len = CMSG_LEN (sizeof (int));
          fd_ptr = (int *) CMSG_DATA (cmsg);
          *fd_ptr = m->sockfd;
          msg.msg_controllen = cmsg->cmsg_len;
     }

     msg.msg_flags = 0;

     if (sendmsg (l->channel.chan, &msg, 0) == -1) {
          i_log (1, "Unable to send message to listener.");
          return -1;
     }
     else {
          if (m->msg == GC_SOCKET && m->sockfd)
               close (m->sockfd);

          return 1;
     }
#endif
}

在上面的代码中,l->channel.chanAF_UNIX套接字,struct message_t是:

struct message_t {
    int msg;
    int sockfd;
};

其中msg可以获得值GC_SOCKETGC_CLOSE。在前一种情况下,字段sockfd包含传递的套接字的描述符,而在后者中没有发送辅助数据(并且工作者应该自杀)。

现在,这些东西不起作用。当主程序将GC_CLOSE发送给工人时,这就是strace所说的:

    ...
    [pid  6229] sendmsg(5, {msg_name(6229)={...}, msg_iov(1)=[{"\1\0\0\0", 4}],
        msg_controllen=0, msg_flags=0}, 0) = -1 EINVAL (Invalid argument)
    ...

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:4)

我认为您没有初始化msg.msg_namemsg.msg_namelen。如果你这样做会更安全:

struct msghdr msg = {}

这相当于调用memset(0)或bzero(),但更简洁。无论如何,现在看起来你正在传递未初始化的谁知道什么,这很容易导致EINVAL。

此外,现在和将来,尝试在valgrind下运行您的程序 - 它可以帮助捕获这样的错误。