2012-02-21 34 views
0

いくつかのコンテキストが最初にあります:ワーカーの束をフォークし、着信接続を待つメインプログラム(Webサーバー)があります。それを受け入れると、ソケット記述子はsendmsg()プリミティブを介してワーカーの1人に送信されます。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.chanAF_UNIXソケットである、とstruct message_tがある:msg、値を取得することができます

struct message_t { 
    int msg; 
    int sockfd; 
}; 

GC_SOCKETまたはGC_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) 
    ... 

助けを借りてください。

答えて

3

msg.msg_namemsg.msg_namelenを初期化していないと思います。より簡潔な

struct msghdr msg = {} 

これはmemsetの(0)またはBZEROを(呼び出すことと同じです)、しかし:それはあなたがこれをしなかった場合は、より安全になります。とにかく今すぐEINVALになる可能性のある、初期化されていない人物を渡しているようです。

また、今後、valgrindの下でプログラムを実行してみてください。このようなエラーをキャッチするのに役立ちます。

+0

ああ。さて、あなたの構造を常にゼロにすることが良い理由です。使用しているAPIは、意味のあるエラー(おそらくあなたのケースではENOTCONN)を報告する機会があります。生活し、学びます。 :) –