Mac OS X: recvmsg возвращает EMSGSIZE при отправке файлов fd через сокет дейтаграммы домена Unix

У меня есть фрагмент кода, который использует сокеты домена Unix и sendmsg / recvmsg для отправки файлов fd между двумя процессами. Этот код должен работать как на Linux, так и на Mac (он выполняется отдельно для обеих платформ). Я использую сокеты SOCK_DGRAM (датаграмма).

Я отправляю по одному fd в своем коде. На Mac после успешной отправки нескольких файлов fd таким образом recvmsg () завершается ошибкой с EMSGSIZE. Согласно справочной странице для recvmsg, это может произойти, только если msg-> msg_iovlen ‹= 0 или> = константа, которая на Mac равна 2048. В моем коде я всегда привязывал msg_iovlen к 1, я проверял это на отправителе и получателе, а также при чтении заголовка сообщения сразу после сбоев recvmsg (). Этот же код отлично работает в Linux.

Другая возможность, если посмотреть на исходный код ядра XNU, состоит в том, что у получателя могли закончиться fd, но я отправил только 4 или 5 fd до того, как произошла ошибка, поэтому должно быть много fd.

Если я не отправляю fd, а отправляю только данные, этой ошибки не возникает.

Вот как выглядит код, упаковывающий управляющее сообщение:

// *obj is the fd, objSize is sizeof(*obj)
// cmsg was allocated earlier as a 512 byte buffer

cmsgLength = CMSG_LEN(objSize);

cmsgSpace = CMSG_SPACE(objSize);

cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = cmsgLength;

memcpy(CMSG_DATA(cmsg), obj, objSize);

msg->msg_control = cmsg;
msg->msg_controllen = cmsgSpace;

А вот и ресивер:

msg = (struct msghdr *)pipe->msg;
iov = msg->msg_iov;
iov->iov_base = buf;
iov->iov_len = size;

// msg->msg_control was set earlier
msg->msg_controllen = 512;

return recvmsg(sockFd, msg, 0);

Какие-нибудь подсказки? заранее спасибо


person Mayank    schedule 24.06.2013    source источник


Ответы (1)


Вы действительно используете cmsg-материалы, которые получаете? Я заметил, что вы установили для msg_controllen значение 512. Что вы установили для msg_flags?

Не могли бы вы попробовать то же самое со следующим дополнением.

msg = (struct msghdr *)pipe->msg;

memset (msg, 0, sizeof(msghdr)); /* added this */

iov = msg->msg_iov;
iov->iov_base = buf;
iov->iov_len = size;

// msg->msg_control was set earlier
msg->msg_controllen = 512;

return recvmsg(sockFd, msg, 0);
person amrith    schedule 18.08.2013