From e62cfe621d6a3206284fddd2af95661edca7f01d Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Wed, 4 Nov 2015 10:38:13 +0800 Subject: [PATCH] socket: Dispose rights directly in soreceive(), if them are not wanted Instead of leaving them to unp_gc(). This paves the way to simplify unp_gc() and to remove filehead. While I'm here, minor style changes. --- sys/kern/uipc_socket.c | 20 ++++++++++++++++---- test/unix/passdesc/passdesc.c | 24 +++++++++++++++++++----- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 7de9418108..04c08b6a60 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1250,6 +1250,7 @@ soreceive(struct socket *so, struct sockaddr **psa, struct uio *uio, struct protosw *pr = so->so_proto; int moff, type = 0; size_t resid, orig_resid; + boolean_t free_rights = FALSE; if (uio) resid = uio->uio_resid; @@ -1395,15 +1396,22 @@ dontblock: *controlp = m_copy(m, 0, m->m_len); m = m->m_next; /* XXX race */ } else { + const struct cmsghdr *cm = mtod(m, struct cmsghdr *); + if (controlp) { n = sbunlinkmbuf(&so->so_rcv.sb, m, NULL); if (pr->pr_domain->dom_externalize && - mtod(m, struct cmsghdr *)->cmsg_type == - SCM_RIGHTS) - error = (*pr->pr_domain->dom_externalize)(m, flags); + cm->cmsg_level == SOL_SOCKET && + cm->cmsg_type == SCM_RIGHTS) { + error = pr->pr_domain->dom_externalize + (m, flags); + } *controlp = m; m = n; } else { + if (cm->cmsg_level == SOL_SOCKET && + cm->cmsg_type == SCM_RIGHTS) + free_rights = TRUE; m = sbunlinkmbuf(&so->so_rcv.sb, m, &free_chain); } } @@ -1564,8 +1572,12 @@ release: ssb_unlock(&so->so_rcv); done: lwkt_reltoken(&so->so_rcv.ssb_token); - if (free_chain) + if (free_chain) { + if (free_rights && (pr->pr_flags & PR_RIGHTS) && + pr->pr_domain->dom_dispose) + pr->pr_domain->dom_dispose(free_chain); m_freem(free_chain); + } return (error); } diff --git a/test/unix/passdesc/passdesc.c b/test/unix/passdesc/passdesc.c index 42fa656ae2..c87bbff360 100644 --- a/test/unix/passdesc/passdesc.c +++ b/test/unix/passdesc/passdesc.c @@ -100,24 +100,29 @@ test_recv_desc(int s) static void usage(const char *cmd) { - fprintf(stderr, "%s [-d]\n", cmd); + fprintf(stderr, "%s [-d] [-s]\n", cmd); exit(1); } int main(int argc, char *argv[]) { - int s[2], fd, status, n, discard; + int s[2], fd, status, n, discard, skipfd; int opt; off_t ofs; discard = 0; - while ((opt = getopt(argc, argv, "d")) != -1) { + skipfd = 0; + while ((opt = getopt(argc, argv, "ds")) != -1) { switch (opt) { case 'd': discard = 1; break; + case 's': + skipfd = 1; + break; + default: usage(argv[0]); } @@ -128,10 +133,19 @@ main(int argc, char *argv[]) if (fork() == 0) { close(s[0]); - if (!discard) + if (!discard && !skipfd) { test_recv_desc(s[1]); - else + } else if (skipfd) { + int buf; + + fprintf(stderr, "skipfd\n"); + n = read(s[1], &buf, sizeof(buf)); + if (n < 0) + err(1, "read failed"); + } else { + fprintf(stderr, "discard msg\n"); sleep(5); + } exit(0); } close(s[1]); -- 2.41.0