Backport #5075 » recvmsg-msg_peek-freebsd.patch
io.c (working copy) | ||
---|---|---|
void
|
||
rb_update_max_fd(int fd)
|
||
{
|
||
struct stat buf;
|
||
if (fstat(fd, &buf) != 0) {
|
||
rb_bug("rb_update_max_fd: invalid fd (%d) given.", fd);
|
||
}
|
||
if (max_file_descriptor < fd) max_file_descriptor = fd;
|
||
}
|
||
ext/socket/rubysocket.h (working copy) | ||
---|---|---|
#endif
|
||
#ifdef HAVE_ST_MSG_CONTROL
|
||
void rsock_discard_cmsg_resource(struct msghdr *mh);
|
||
void rsock_discard_cmsg_resource(struct msghdr *mh, int msg_peek_p);
|
||
#endif
|
||
void rsock_init_basicsocket(void);
|
ext/socket/ancdata.c (working copy) | ||
---|---|---|
#if defined(HAVE_ST_MSG_CONTROL)
|
||
static void
|
||
discard_cmsg(struct cmsghdr *cmh, char *msg_end)
|
||
discard_cmsg(struct cmsghdr *cmh, char *msg_end, int msg_peek_p)
|
||
{
|
||
# if defined(__FreeBSD__) || defined(__APPLE__)
|
||
/*
|
||
* naruse investigated that FreeBSD 8.2.0 doesn't return fds if MSG_PEEK is
|
||
* specified. [ruby-dev:44189]
|
||
* kosaki confirmed MacOS X Lion inherits it. [ruby-dev:44192]
|
||
*/
|
||
if (msg_peek_p)
|
||
return;
|
||
# endif
|
||
if (cmh->cmsg_level == SOL_SOCKET && cmh->cmsg_type == SCM_RIGHTS) {
|
||
int *fdp = (int *)CMSG_DATA(cmh);
|
||
int *end = (int *)((char *)cmh + cmh->cmsg_len);
|
||
while ((char *)fdp + sizeof(int) <= (char *)end &&
|
||
(char *)fdp + sizeof(int) <= msg_end) {
|
||
/*
|
||
* xxx: nagachika said *fdp can be invalid fd on MacOS X Lion.
|
||
* This workaround using fstat is clearly wrong.
|
||
* we should investigate why *fdp contains invalid fd.
|
||
*/
|
||
struct stat buf;
|
||
if (fstat(*fdp, &buf) == 0) {
|
||
rb_update_max_fd(*fdp);
|
||
close(*fdp);
|
||
}
|
||
rb_update_max_fd(*fdp);
|
||
close(*fdp);
|
||
fdp++;
|
||
}
|
||
}
|
||
... | ... | |
#endif
|
||
void
|
||
rsock_discard_cmsg_resource(struct msghdr *mh)
|
||
rsock_discard_cmsg_resource(struct msghdr *mh, int msg_peek_p)
|
||
{
|
||
#if defined(HAVE_ST_MSG_CONTROL)
|
||
struct cmsghdr *cmh;
|
||
... | ... | |
msg_end = (char *)mh->msg_control + mh->msg_controllen;
|
||
for (cmh = CMSG_FIRSTHDR(mh); cmh != NULL; cmh = CMSG_NXTHDR(mh, cmh)) {
|
||
discard_cmsg(cmh, msg_end);
|
||
discard_cmsg(cmh, msg_end, msg_peek_p);
|
||
}
|
||
#endif
|
||
}
|
||
... | ... | |
/* there are big space bug truncated.
|
||
* file descriptors limit? */
|
||
if (!gc_done) {
|
||
rsock_discard_cmsg_resource(&mh);
|
||
rsock_discard_cmsg_resource(&mh, (flags & MSG_PEEK) != 0);
|
||
goto gc_and_retry;
|
||
}
|
||
}
|
||
... | ... | |
}
|
||
#endif
|
||
if (grown) {
|
||
rsock_discard_cmsg_resource(&mh);
|
||
rsock_discard_cmsg_resource(&mh, (flags & MSG_PEEK) != 0);
|
||
goto retry;
|
||
}
|
||
else {
|
||
grow_buffer = 0;
|
||
if (flags != orig_flags) {
|
||
rsock_discard_cmsg_resource(&mh, (flags & MSG_PEEK) != 0);
|
||
flags = orig_flags;
|
||
rsock_discard_cmsg_resource(&mh);
|
||
goto retry;
|
||
}
|
||
}
|
||
... | ... | |
if (request_scm_rights)
|
||
make_io_for_unix_rights(ctl, cmh, msg_end);
|
||
else
|
||
discard_cmsg(cmh, msg_end);
|
||
discard_cmsg(cmh, msg_end, (flags & MSG_PEEK) != 0);
|
||
rb_ary_push(ret, ctl);
|
||
}
|
||
}
|
ext/socket/unixsocket.c (working copy) | ||
---|---|---|
(int)arg.msg.msg_controllen, (int)CMSG_SPACE(sizeof(int)));
|
||
}
|
||
if (cmsg.hdr.cmsg_len != CMSG_LEN(sizeof(int))) {
|
||
rsock_discard_cmsg_resource(&arg.msg);
|
||
rsock_discard_cmsg_resource(&arg.msg, 0);
|
||
rb_raise(rb_eSocket,
|
||
"file descriptor was not passed (cmsg_len=%d, %d expected)",
|
||
(int)cmsg.hdr.cmsg_len, (int)CMSG_LEN(sizeof(int)));
|