I am utilizing a UNIX domain socket to transfer personal files descriptor to a different process. This works fine, but initially when i first concept if socket is writeable using choose(), the sendmsg() call fails having a Bad File Descriptor error.

The sendmsg() function works fine in conjunction with choose() basically don't add the file descriptor info towards the msghdr struct, therefore the conflict appears to become between choose() and moving file descriptors.

I could not find any information on this within the guy pages for choose(), recvmsg(), or other. Because this needs to become server which hands out file descriptors to multiple processes, I'd still prefer to have the ability to use choose().

Can there be anything I'm able to do to make this happen, or does anybody are conscious of alternative solutions?

Platform is Ubuntu 10.4.

This is actually the code that initializes the structures:



struct cmsghdr_fd : public cmsghdr
{
  int fd;
};

int sendfd(int sock, int fd)
{
  struct msghdr hdr;
  struct iovec data;
  struct cmsghdr_fd msgdata;

  char dummy = '*';
  data.iov_base = &dummy;
  data.iov_len = sizeof(dummy);

  hdr.msg_name = NULL;
  hdr.msg_namelen = 0;
  hdr.msg_iov = &data;
  hdr.msg_iovlen = 1;
  hdr.msg_flags = 0;

  hdr.msg_control = &msgdata;
  hdr.msg_controllen = sizeof(msgdata);

  struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr);
  cmsg->cmsg_len   = hdr.msg_controllen;
  cmsg->cmsg_level = SOL_SOCKET;
  cmsg->cmsg_type  = SCM_RIGHTS;

  *(int*)CMSG_DATA(cmsg) = fd;

  int n = sendmsg(sock, &hdr, 0);

  if(n == -1)
    printf("sendmsg() failed: %s (socket fd = %d)\n", strerror(errno), sock);

  return n;
}

Again, this works, as lengthy when i don't call choose() first to check on if the socket is prepared for writing.

I attempted the sendfd code at this page, that was kindly supplied by nos, and despite the fact that it's only slightly different, it really works even if I personally use it in conjunction with choose(). This is exactly what the code appears like now:


int sendfd(int sock, int fd)
{
  struct msghdr hdr;
  struct iovec data;

  char cmsgbuf[CMSG_SPACE(sizeof(int))];

  char dummy = '*';
  data.iov_base = &dummy;
  data.iov_len = sizeof(dummy);

  memset(&hdr, 0, sizeof(hdr));
  hdr.msg_name = NULL;
  hdr.msg_namelen = 0;
  hdr.msg_iov = &data;
  hdr.msg_iovlen = 1;
  hdr.msg_flags = 0;

  hdr.msg_control = cmsgbuf;
  hdr.msg_controllen = CMSG_LEN(sizeof(int));

  struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr);
  cmsg->cmsg_len   = CMSG_LEN(sizeof(int));
  cmsg->cmsg_level = SOL_SOCKET;
  cmsg->cmsg_type  = SCM_RIGHTS;

  *(int*)CMSG_DATA(cmsg) = fd;

  int n = sendmsg(sock, &hdr, 0);

  if(n == -1)
    printf("sendmsg() failed: %s (socket fd = %d)\n", strerror(errno), sock);

  return n;
}