2012-02-21 2 views
0

В некотором контексте сначала есть основная программа (веб-сервер), которая разворачивает кучу работников и ждет входящих соединений. Когда он принимает один, он отправляет дескриптор сокета одному из рабочих через примитив sendmsg().sendmsg() недопустимые аргументы (??)

Это код, который должен отправить дескриптор:

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.chan является AF_UNIX гнездо, и struct message_t является:

struct message_t { 
    int msg; 
    int sockfd; 
}; 

где msg можно получить значения GC_SOCKET или GC_CLOSE. В первом случае поле sockfd содержит дескриптор сокета, прошедшего, а в последнем не передаются вспомогательные данные (и работник должен убить себя).

Теперь этот материал не работает. Это то, что Трассирование говорит об этом, когда основная программа посылает GC_CLOSE работнику:

... 
    [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) 
    ... 

Любая помощь очень ценится.

ответ

3

Я думаю, что вы не инициализируете msg.msg_name и msg.msg_namelen. Было бы безопаснее, если вы сделали это:

struct msghdr msg = {} 

Это эквивалентно вызову MemSet (0) или bzero(), но более кратким. В любом случае, похоже, что вы передаете неинициализированный, кто знает, что может легко привести к EINVAL.

Кроме того, теперь и в будущем попробуйте запустить вашу программу под valgrind - это может помочь поймать ошибки, подобные этому.

+0

Ох. Ну, вот почему это хорошая идея, чтобы всегда обнулить ваши структуры - тогда используемые вами API имеют шанс сразиться с осмысленной ошибкой (возможно, ENOTCONN в вашем случае). Живи и учись. :) –

Смежные вопросы