I'm sending messages on Unix domain sockets on Mac with sendmsg()
. However, it sometimes hangs forever.
I've called getsockopt(socket, SOL_SOCKET, SO_SNDBUF, ...)
to get the size of the send buffer. (The default is 2048
).
- If I try sending a message larger than
2048
bytes, I correctly getEMSGSIZE
and know I need to send a smaller message. - If I try sending a message less than
2036
bytes, the message is sent fine. - If I try sending a message between
2036
and2048
bytes, thesendmsg
call...hangs forever.
What's going on here? What's the correct way to deal with this? Is it safe to just subtract 13 bytes from the maximum size I try sending, or could I run into issues if e.g. there's other messages in the buffer already?
Here's the (simplified) code I'm using:
// Get the maximum message size
int MaxMessageSize(int socket) {
int sndbuf = 0;
socklen_t optlen = sizeof(sndbuf);
if (getsockopt(socket, SOL_SOCKET, SO_SNDBUF, &sndbuf, &optlen) < 0) {
return -1;
}
return sndbuf;
}
// Send a message
static int send_chunk(int socket, const char *data, size_t size) {
struct msghdr msg = {0};
char buf[CMSG_SPACE(0)];
memset(buf, '\0', sizeof(buf));
int iov_len = size;
if (iov_len > 512) {
int stat = send_size(socket, iov_len);
if (stat < 0) return stat;
}
char iov_buf[iov_len];
memcpy(iov_buf, data, size);
struct iovec io = {.iov_base = (void *)iov_buf, .iov_len = iov_len};
msg.msg_iov = &io;
msg.msg_iovlen = 1;
msg.msg_control = buf;
msg.msg_controllen = sizeof(buf);
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(0);
msg.msg_controllen = CMSG_SPACE(0);
std::cerr << "Attempting to send message of size " << iov_len << std::endl;
ssize_t ret = sendmsg(socket, &msg, 0);
std::cerr << "sendmsg returned: " << ret << std::endl;
return ret;
}