From: Eric Blake <eblake@redhat.com>
To: Stefan Hajnoczi <stefanha@redhat.com>, qemu-devel@nongnu.org
Cc: Paolo Bonzini <pbonzini@redhat.com>,
Gerd Hoffmann <kraxel@redhat.com>,
Daniel Berrange <berrange@redhat.com>
Subject: Re: [Qemu-devel] [PATCH] socket: add atomic QEMU_SOCK_NONBLOCK flag
Date: Fri, 7 Oct 2016 10:55:55 -0500 [thread overview]
Message-ID: <b2cc4889-6255-f96e-1a36-af47d797b2c1@redhat.com> (raw)
In-Reply-To: <1475848458-1285-1-git-send-email-stefanha@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 5577 bytes --]
On 10/07/2016 08:54 AM, Stefan Hajnoczi wrote:
> The socket(2) and accept(2) syscalls have been extended to take flags
> that affect the socket atomically at creation time. This not only
> avoids the overhead of additional system calls but also closes the race
> condition with forking threads.
>
> This patch adds support for the SOCK_NONBLOCK flag. QEMU already
> implements the SOCK_CLOEXEC flag.
Atomic where supported by the OS, racy fallback on older systems, but
not the end of the world (and our already-existing fallback is already
racy, where the SOCK_CLOEXEC race is more likely to affect a
multithreaded forking app, while SOCK_NONBLOCK is just there for
convenience).
>
> All qemu_socket() and qemu_accept() callers are updated to pass the new
> flags argument. Callers that later use qemu_set_nonblock() are
> refactored as follows:
>
> fd = qemu_socket(...) or qemu_accept(...);
> ...
> qemu_set_nonblock(fd);
>
> Becomes:
>
> fd = qemu_socket(..., QEMU_SOCK_NONBLOCK) or
> qemu_accept(..., QEMU_SOCK_NONBLOCK);
>
> For full details on SOCK_NONBLOCK in the POSIX spec see:
> http://austingroupbugs.net/view.php?id=411
/me that looks strangely familiar... :)
>
> Note that slirp code violates the coding style with a mix of tabs and
> space indentation. This patch passes checkpatch.pl but the diff may
> appear odd due to the mixed indentation in slirp code.
>
> Suggested-by: Eric Blake <eblake@redhat.com>
> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> ---
> +++ b/include/qemu/sockets.h
> @@ -11,9 +11,14 @@ int inet_aton(const char *cp, struct in_addr *ia);
>
> #include "qapi-types.h"
>
> +typedef enum {
> + QEMU_SOCK_NONBLOCK = 1,
> +} QemuSockFlags;
Good, since we can't rely on SOCK_NONBLOCK being defined everywhere yet.
> --- a/slirp/misc.c
> +++ b/slirp/misc.c
> @@ -184,13 +185,13 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
> * of connect() fail in the child process
> */
> do {
> - so->s = accept(s, (struct sockaddr *)&addr, &addrlen);
> + so->s = qemu_accept(s, (struct sockaddr *)&addr, &addrlen,
> + QEMU_SOCK_NONBLOCK);
Silent bug fix here and elsewhere that we now set CLOEXEC where we
previously didn't. Probably worth mentioning in the commit message that
you fixed a couple of places that used accept() instead of the proper
qemu_accept().
> +++ b/util/osdep.c
> @@ -267,12 +267,21 @@ ssize_t qemu_write_full(int fd, const void *buf, size_t count)
> /*
> * Opens a socket with FD_CLOEXEC set
> */
> -int qemu_socket(int domain, int type, int protocol)
> +int qemu_socket(int domain, int type, int protocol, QemuSockFlags flags)
> {
> int ret;
>
> -#ifdef SOCK_CLOEXEC
> - ret = socket(domain, type | SOCK_CLOEXEC, protocol);
> + /* Require both SOCK_CLOEXEC and SOCK_NONBLOCK to avoid additional cases
> + * with only one defined. Both were added to POSIX in Austin Group #411 so
> + * chances are good they come in a pair.
Indeed.
> @@ -288,12 +300,17 @@ int qemu_socket(int domain, int type, int protocol)
> /*
> * Accept a connection and set FD_CLOEXEC
> */
> -int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
> +int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen,
> + QemuSockFlags flags)
> {
> int ret;
>
> #ifdef CONFIG_ACCEPT4
> - ret = accept4(s, addr, addrlen, SOCK_CLOEXEC);
> + int accept_flags = SOCK_CLOEXEC;
> + if (flags & QEMU_SOCK_NONBLOCK) {
> + accept_flags |= SOCK_NONBLOCK;
> + }
You're also (implicitly) assuming that CONFIG_ACCEPT4 implies both
SOCK_CLOEXEC and SOCK_NONBLOCK; again likely to be true.
> @@ -317,18 +318,20 @@ static int inet_connect_addr(struct addrinfo *addr, bool *in_progress,
> ConnectState *connect_state, Error **errp)
> {
> int sock, rc;
> + QemuSockFlags flags = 0;
>
> *in_progress = false;
>
> - sock = qemu_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
> - if (sock < 0) {
> - error_setg_errno(errp, errno, "Failed to create socket");
> - return -1;
> - }
> - socket_set_fast_reuse(sock);
> if (connect_state != NULL) {
> - qemu_set_nonblock(sock);
> + flags = QEMU_SOCK_NONBLOCK;
Use |= here? ...
> @@ -732,16 +737,16 @@ static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp,
> return -1;
> }
>
> - sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
> - if (sock < 0) {
> - error_setg_errno(errp, errno, "Failed to create socket");
> - return -1;
> - }
> if (callback != NULL) {
> connect_state = g_malloc0(sizeof(*connect_state));
> connect_state->callback = callback;
> connect_state->opaque = opaque;
> - qemu_set_nonblock(sock);
> + flags |= QEMU_SOCK_NONBLOCK;
> + }
...to match how you did it here? (No current semantic difference, but
might lead to future maintenance problems if further additions aren't
careful.)
I found a minor nit and some suggested commit message improvements, but
the patch itself is sane enough that I'm okay if you add:
Reviewed-by: Eric Blake <eblake@redhat.com>
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]
next prev parent reply other threads:[~2016-10-07 15:56 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-10-07 13:54 [Qemu-devel] [PATCH] socket: add atomic QEMU_SOCK_NONBLOCK flag Stefan Hajnoczi
2016-10-07 15:55 ` Eric Blake [this message]
2016-10-12 15:11 ` Stefan Hajnoczi
2016-10-10 19:05 ` no-reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=b2cc4889-6255-f96e-1a36-af47d797b2c1@redhat.com \
--to=eblake@redhat.com \
--cc=berrange@redhat.com \
--cc=kraxel@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).