Project

General

Profile

Backport #5075 ยป recvmsg-msg_peek-freebsd.patch

akr (Akira Tanaka), 07/23/2011 01:47 AM

View differences:

io.c (working copy)
154 154
void
155 155
rb_update_max_fd(int fd)
156 156
{
157
    struct stat buf;
158
    if (fstat(fd, &buf) != 0) {
159
        rb_bug("rb_update_max_fd: invalid fd (%d) given.", fd);
160
    }
157 161
    if (max_file_descriptor < fd) max_file_descriptor = fd;
158 162
}
159 163

  
ext/socket/rubysocket.h (working copy)
288 288
#endif
289 289

  
290 290
#ifdef HAVE_ST_MSG_CONTROL
291
void rsock_discard_cmsg_resource(struct msghdr *mh);
291
void rsock_discard_cmsg_resource(struct msghdr *mh, int msg_peek_p);
292 292
#endif
293 293

  
294 294
void rsock_init_basicsocket(void);
ext/socket/ancdata.c (working copy)
1377 1377

  
1378 1378
#if defined(HAVE_ST_MSG_CONTROL)
1379 1379
static void
1380
discard_cmsg(struct cmsghdr *cmh, char *msg_end)
1380
discard_cmsg(struct cmsghdr *cmh, char *msg_end, int msg_peek_p)
1381 1381
{
1382
# if defined(__FreeBSD__) || defined(__APPLE__)
1383
    /* 
1384
     * naruse investigated that FreeBSD 8.2.0 doesn't return fds if MSG_PEEK is
1385
     * specified.  [ruby-dev:44189]
1386
     * kosaki confirmed MacOS X Lion inherits it.   [ruby-dev:44192]
1387
     */
1388
    if (msg_peek_p)
1389
        return;
1390
# endif
1382 1391
    if (cmh->cmsg_level == SOL_SOCKET && cmh->cmsg_type == SCM_RIGHTS) {
1383 1392
        int *fdp = (int *)CMSG_DATA(cmh);
1384 1393
        int *end = (int *)((char *)cmh + cmh->cmsg_len);
1385 1394
        while ((char *)fdp + sizeof(int) <= (char *)end &&
1386 1395
               (char *)fdp + sizeof(int) <= msg_end) {
1387
            /*
1388
             * xxx: nagachika said *fdp can be invalid fd on MacOS X Lion.
1389
             * This workaround using fstat is clearly wrong.
1390
             * we should investigate why *fdp contains invalid fd.
1391
             */
1392
            struct stat buf;
1393
            if (fstat(*fdp, &buf) == 0) {
1394
                rb_update_max_fd(*fdp);
1395
                close(*fdp);
1396
            }
1396
            rb_update_max_fd(*fdp);
1397
            close(*fdp);
1397 1398
            fdp++;
1398 1399
        }
1399 1400
    }
......
1401 1402
#endif
1402 1403

  
1403 1404
void
1404
rsock_discard_cmsg_resource(struct msghdr *mh)
1405
rsock_discard_cmsg_resource(struct msghdr *mh, int msg_peek_p)
1405 1406
{
1406 1407
#if defined(HAVE_ST_MSG_CONTROL)
1407 1408
    struct cmsghdr *cmh;
......
1413 1414
    msg_end = (char *)mh->msg_control + mh->msg_controllen;
1414 1415

  
1415 1416
    for (cmh = CMSG_FIRSTHDR(mh); cmh != NULL; cmh = CMSG_NXTHDR(mh, cmh)) {
1416
        discard_cmsg(cmh, msg_end);
1417
        discard_cmsg(cmh, msg_end, msg_peek_p);
1417 1418
    }
1418 1419
#endif
1419 1420
}
......
1612 1613
                /* there are big space bug truncated.
1613 1614
                 * file descriptors limit? */
1614 1615
                if (!gc_done) {
1615
		    rsock_discard_cmsg_resource(&mh);
1616
		    rsock_discard_cmsg_resource(&mh, (flags & MSG_PEEK) != 0);
1616 1617
                    goto gc_and_retry;
1617 1618
		}
1618 1619
            }
......
1633 1634
	}
1634 1635
#endif
1635 1636
	if (grown) {
1636
            rsock_discard_cmsg_resource(&mh);
1637
            rsock_discard_cmsg_resource(&mh, (flags & MSG_PEEK) != 0);
1637 1638
	    goto retry;
1638 1639
	}
1639 1640
	else {
1640 1641
            grow_buffer = 0;
1641 1642
            if (flags != orig_flags) {
1643
                rsock_discard_cmsg_resource(&mh, (flags & MSG_PEEK) != 0);
1642 1644
                flags = orig_flags;
1643
                rsock_discard_cmsg_resource(&mh);
1644 1645
                goto retry;
1645 1646
            }
1646 1647
        }
......
1680 1681
            if (request_scm_rights)
1681 1682
                make_io_for_unix_rights(ctl, cmh, msg_end);
1682 1683
            else
1683
                discard_cmsg(cmh, msg_end);
1684
                discard_cmsg(cmh, msg_end, (flags & MSG_PEEK) != 0);
1684 1685
            rb_ary_push(ret, ctl);
1685 1686
        }
1686 1687
    }
ext/socket/unixsocket.c (working copy)
367 367
		 (int)arg.msg.msg_controllen, (int)CMSG_SPACE(sizeof(int)));
368 368
    }
369 369
    if (cmsg.hdr.cmsg_len != CMSG_LEN(sizeof(int))) {
370
	rsock_discard_cmsg_resource(&arg.msg);
370
	rsock_discard_cmsg_resource(&arg.msg, 0);
371 371
	rb_raise(rb_eSocket,
372 372
		 "file descriptor was not passed (cmsg_len=%d, %d expected)",
373 373
		 (int)cmsg.hdr.cmsg_len, (int)CMSG_LEN(sizeof(int)));