qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Anthony Liguori <aliguori@us.ibm.com>
To: Markus Armbruster <armbru@redhat.com>
Cc: kwolf@redhat.com, qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH 09/19] sockets: Chardev open error reporting, sockets part
Date: Tue, 07 Feb 2012 09:13:10 -0600	[thread overview]
Message-ID: <4F313F86.7080103@us.ibm.com> (raw)
In-Reply-To: <1328623766-12287-10-git-send-email-armbru@redhat.com>

On 02/07/2012 08:09 AM, Markus Armbruster wrote:
> Convert to error_report().  This adds error locations to the messages,
> which is particularly important when the location is buried in a
> configuration file.  Moreover, we'll need this when we create a
> monitor command to add character devices, so its errors actually
> appear in the monitor, not stderr.
>
> Also clean up the messages, and get rid of some that look like errors,
> but aren't.
>
> Improves user-hostile messages like this one for "-chardev
> socket,id=foo,host=blackfin,port=1,server"
>
>      inet_listen_opts: bind(ipv4,192.168.2.9,1): Permission denied
>      chardev: opening backend "socket" failed
>
> to
>
>      qemu-system-x86_64: -chardev socket,id=foo,host=blackfin,port=1,server: Can't bind port blackfin:1: Permission denied
>      chardev: opening backend "socket" failed
>
> and this one for "-chardev udp,id=foo,localport=1,port=1"
>
>      inet_dgram_opts: bind(ipv4,0.0.0.0,1): OK
>      inet_dgram_opts failed
>      chardev: opening backend "udp" failed
>
> to
>
>      qemu-system-x86_64: -chardev udp,id=foo,localport=1,port=1: Can't bind port :1: Permission denied
>      chardev: opening backend "udp" failed
>
> You got to love the "OK" part.
>
> The uninformative extra "opening backend failed" message will be
> cleaned up shortly.
>
> Signed-off-by: Markus Armbruster<armbru@redhat.com>
> ---
>   qemu-char.c    |    1 -
>   qemu-sockets.c |  154 +++++++++++++++++++++++++------------------------------
>   2 files changed, 70 insertions(+), 85 deletions(-)
>
> diff --git a/qemu-char.c b/qemu-char.c
> index bb9e3f5..d591f70 100644
> --- a/qemu-char.c
> +++ b/qemu-char.c
> @@ -2101,7 +2101,6 @@ static CharDriverState *qemu_chr_open_udp(QemuOpts *opts)
>
>       fd = inet_dgram_opts(opts);
>       if (fd<  0) {
> -        fprintf(stderr, "inet_dgram_opts failed\n");
>           goto return_err;
>       }

Let's add an Error ** argument here.

It's easy to bridge errors to error_report (qerror_report_err) so it's conducive 
to incremental refactoring.  Plus it starts getting us away from terminal errors 
and into proper erroro propagation.

> diff --git a/qemu-sockets.c b/qemu-sockets.c
> index 6bcb8e3..67e0559 100644
> --- a/qemu-sockets.c
> +++ b/qemu-sockets.c
> @@ -20,7 +20,8 @@
>   #include<unistd.h>
>
>   #include "qemu_socket.h"
> -#include "qemu-common.h" /* for qemu_isdigit */
> +#include "qemu-common.h"
> +#include "qemu-error.h"
>
>   #ifndef AI_ADDRCONFIG
>   # define AI_ADDRCONFIG 0
> @@ -107,7 +108,7 @@ int inet_listen_opts(QemuOpts *opts, int port_offset)
>       char port[33];
>       char uaddr[INET6_ADDRSTRLEN+1];
>       char uport[33];
> -    int slisten, rc, to, port_min, port_max, p;
> +    int slisten, rc, to, port_min, port_max, p, sav_errno;
>
>       memset(&ai,0, sizeof(ai));
>       ai.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
> @@ -116,7 +117,7 @@ int inet_listen_opts(QemuOpts *opts, int port_offset)
>
>       if ((qemu_opt_get(opts, "host") == NULL) ||
>           (qemu_opt_get(opts, "port") == NULL)) {
> -        fprintf(stderr, "%s: host and/or port not specified\n", __FUNCTION__);
> +        error_report("inet socket character device requires parameters host and port");
>           return -1;
>       }
>       pstrcpy(port, sizeof(port), qemu_opt_get(opts, "port"));
> @@ -133,8 +134,8 @@ int inet_listen_opts(QemuOpts *opts, int port_offset)
>           snprintf(port, sizeof(port), "%d", atoi(port) + port_offset);
>       rc = getaddrinfo(strlen(addr) ? addr : NULL, port,&ai,&res);
>       if (rc != 0) {
> -        fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port,
> -                gai_strerror(rc));
> +        error_report("Can't resolve %s:%s: %s",
> +                     addr, port, gai_strerror(rc));
>           return -1;
>       }
>
> @@ -145,9 +146,7 @@ int inet_listen_opts(QemuOpts *opts, int port_offset)
>   		        NI_NUMERICHOST | NI_NUMERICSERV);
>           slisten = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol);
>           if (slisten<  0) {
> -            fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
> -                    inet_strfamily(e->ai_family), strerror(errno));
> -            continue;
> +            continue;           /* try next address */
>           }
>
>           setsockopt(slisten,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
> @@ -166,25 +165,33 @@ int inet_listen_opts(QemuOpts *opts, int port_offset)
>               if (bind(slisten, e->ai_addr, e->ai_addrlen) == 0) {
>                   goto listen;
>               }
> -            if (p == port_max) {
> -                fprintf(stderr,"%s: bind(%s,%s,%d): %s\n", __FUNCTION__,
> -                        inet_strfamily(e->ai_family), uaddr, inet_getport(e),
> -                        strerror(errno));
> -            }
>           }
> +
> +        sav_errno = errno;
>           closesocket(slisten);
> +        errno = sav_errno;
> +        /* try next address */
> +    }
> +
> +    /* no address worked, errno is from last failed socket() or bind() */
> +    if (to) {
> +        error_report("Can't bind any port %s:%s..%d: %s",
> +                     addr, port, to, strerror(errno));
> +    } else {
> +        error_report("Can't bind port %s:%s: %s",
> +                     addr, port, strerror(errno));
>       }
> -    fprintf(stderr, "%s: FAILED\n", __FUNCTION__);
>       freeaddrinfo(res);
>       return -1;
>
>   listen:
>       if (listen(slisten,1) != 0) {
> -        perror("listen");
> +        error_report("Can't listen on %s:%d: %s", addr, p, strerror(errno));
>           closesocket(slisten);
>           freeaddrinfo(res);
>           return -1;
>       }
> +
>       snprintf(uport, sizeof(uport), "%d", inet_getport(e) - port_offset);
>       qemu_opt_set(opts, "host", uaddr);
>       qemu_opt_set(opts, "port", uport);
> @@ -199,8 +206,6 @@ int inet_connect_opts(QemuOpts *opts)
>       struct addrinfo ai,*res,*e;
>       const char *addr;
>       const char *port;
> -    char uaddr[INET6_ADDRSTRLEN+1];
> -    char uport[33];
>       int sock,rc;
>
>       memset(&ai,0, sizeof(ai));
> @@ -211,7 +216,7 @@ int inet_connect_opts(QemuOpts *opts)
>       addr = qemu_opt_get(opts, "host");
>       port = qemu_opt_get(opts, "port");
>       if (addr == NULL || port == NULL) {
> -        fprintf(stderr, "inet_connect: host and/or port not specified\n");
> +        error_report("inet socket character device requires parameters host and port");
>           return -1;
>       }
>
> @@ -222,38 +227,29 @@ int inet_connect_opts(QemuOpts *opts)
>
>       /* lookup */
>       if (0 != (rc = getaddrinfo(addr, port,&ai,&res))) {
> -        fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port,
> -                gai_strerror(rc));
> +        error_report("Can't resolve %s:%s: %s",
> +                     addr, port, gai_strerror(rc));
>   	return -1;
>       }
>
>       for (e = res; e != NULL; e = e->ai_next) {
> -        if (getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
> -                            uaddr,INET6_ADDRSTRLEN,uport,32,
> -                            NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
> -            fprintf(stderr,"%s: getnameinfo: oops\n", __FUNCTION__);
> -            continue;
> -        }
>           sock = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol);
>           if (sock<  0) {
> -            fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
> -            inet_strfamily(e->ai_family), strerror(errno));
> -            continue;
> +            continue;           /* try next address */
>           }
>           setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
>
>           /* connect to peer */
>           if (connect(sock,e->ai_addr,e->ai_addrlen)<  0) {
> -            if (NULL == e->ai_next)
> -                fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__,
> -                        inet_strfamily(e->ai_family),
> -                        e->ai_canonname, uaddr, uport, strerror(errno));
>               closesocket(sock);
> -            continue;
> +            continue;           /* try next address */
>           }
>           freeaddrinfo(res);
>           return sock;
>       }
> +
> +    /* no address worked, errno is from last failed socket() or connect() */
> +    error_report("Can't connect to %s:%s: %s", addr, port, strerror(errno));
>       freeaddrinfo(res);
>       return -1;
>   }
> @@ -261,12 +257,9 @@ int inet_connect_opts(QemuOpts *opts)
>   int inet_dgram_opts(QemuOpts *opts)
>   {
>       struct addrinfo ai, *peer = NULL, *local = NULL;
> -    const char *addr;
> -    const char *port;
> -    char uaddr[INET6_ADDRSTRLEN+1];
> -    char uport[33];
> +    const char *addr, *port;
> +    const char *localaddr, *localport;
>       int sock = -1, rc;
> -
>       /* lookup peer addr */
>       memset(&ai,0, sizeof(ai));
>       ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
> @@ -279,7 +272,7 @@ int inet_dgram_opts(QemuOpts *opts)
>           addr = "localhost";
>       }
>       if (port == NULL || strlen(port) == 0) {
> -        fprintf(stderr, "inet_dgram: port not specified\n");
> +        error_report("udp character device requires parameter port");
>           return -1;
>       }
>
> @@ -289,8 +282,8 @@ int inet_dgram_opts(QemuOpts *opts)
>           ai.ai_family = PF_INET6;
>
>       if (0 != (rc = getaddrinfo(addr, port,&ai,&peer))) {
> -        fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port,
> -                gai_strerror(rc));
> +        error_report("Can't resolve %s:%s: %s",
> +                     addr, port, gai_strerror(rc));
>   	return -1;
>       }
>
> @@ -300,53 +293,40 @@ int inet_dgram_opts(QemuOpts *opts)
>       ai.ai_family = peer->ai_family;
>       ai.ai_socktype = SOCK_DGRAM;
>
> -    addr = qemu_opt_get(opts, "localaddr");
> -    port = qemu_opt_get(opts, "localport");
> -    if (addr == NULL || strlen(addr) == 0) {
> -        addr = NULL;
> +    localaddr = qemu_opt_get(opts, "localaddr");
> +    localport = qemu_opt_get(opts, "localport");
> +    if (localaddr == NULL || strlen(localaddr) == 0) {
> +        localaddr = NULL;
>       }
> -    if (!port || strlen(port) == 0)
> -        port = "0";
> +    if (!localport || strlen(localport) == 0)
> +        localport = "0";
>
> -    if (0 != (rc = getaddrinfo(addr, port,&ai,&local))) {
> -        fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port,
> -                gai_strerror(rc));
> +    if (0 != (rc = getaddrinfo(localaddr, localport,&ai,&local))) {
> +        error_report("Can't resolve %s:%s: %s",
> +                     localaddr ? localaddr : NULL, localport,
> +                     gai_strerror(rc));
>           return -1;
>       }
>
>       /* create socket */
>       sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol);
>       if (sock<  0) {
> -        fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
> -                inet_strfamily(peer->ai_family), strerror(errno));
> -        goto err;
> +        goto cant_bind;
>       }
>       setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
>
>       /* bind socket */
> -    if (getnameinfo((struct sockaddr*)local->ai_addr,local->ai_addrlen,
> -                    uaddr,INET6_ADDRSTRLEN,uport,32,
> -                    NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
> -        fprintf(stderr, "%s: getnameinfo: oops\n", __FUNCTION__);
> -        goto err;
> -    }
>       if (bind(sock, local->ai_addr, local->ai_addrlen)<  0) {
> -        fprintf(stderr,"%s: bind(%s,%s,%d): OK\n", __FUNCTION__,
> -                inet_strfamily(local->ai_family), uaddr, inet_getport(local));
> +    cant_bind:
> +        error_report("Can't bind port %s:%s: %s",
> +                     localaddr ? localaddr : "", localport, strerror(errno));
>           goto err;
>       }
>
>       /* connect to peer */
> -    if (getnameinfo((struct sockaddr*)peer->ai_addr, peer->ai_addrlen,
> -                    uaddr, INET6_ADDRSTRLEN, uport, 32,
> -                    NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
> -        fprintf(stderr, "%s: getnameinfo: oops\n", __FUNCTION__);
> -        goto err;
> -    }
>       if (connect(sock,peer->ai_addr,peer->ai_addrlen)<  0) {
> -        fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__,
> -                inet_strfamily(peer->ai_family),
> -                peer->ai_canonname, uaddr, uport, strerror(errno));
> +        error_report("Can't connect to %s:%s: %s",
> +                     addr, port, strerror(errno));
>           goto err;
>       }
>
> @@ -471,8 +451,7 @@ int unix_listen_opts(QemuOpts *opts)
>
>       sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
>       if (sock<  0) {
> -        perror("socket(unix)");
> -        return -1;
> +        goto err;
>       }
>
>       memset(&un, 0, sizeof(un));
> @@ -496,18 +475,20 @@ int unix_listen_opts(QemuOpts *opts)
>
>       unlink(un.sun_path);
>       if (bind(sock, (struct sockaddr*)&un, sizeof(un))<  0) {
> -        fprintf(stderr, "bind(unix:%s): %s\n", un.sun_path, strerror(errno));
>           goto err;
>       }
>       if (listen(sock, 1)<  0) {
> -        fprintf(stderr, "listen(unix:%s): %s\n", un.sun_path, strerror(errno));
>           goto err;
>       }
>
>       return sock;
>
>   err:
> -    closesocket(sock);
> +    error_report("Can't create socket %s: %s",
> +                 un.sun_path, strerror(errno));
> +    if (sock>= 0) {
> +        closesocket(sock);
> +    }
>       return -1;
>   }
>
> @@ -518,26 +499,31 @@ int unix_connect_opts(QemuOpts *opts)
>       int sock;
>
>       if (NULL == path) {
> -        fprintf(stderr, "unix connect: no path specified\n");
> +        error_report("unix socket character device requires parameter path");
>           return -1;
>       }
>
>       sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
>       if (sock<  0) {
> -        perror("socket(unix)");
> -        return -1;
> +        goto err;
>       }
>
>       memset(&un, 0, sizeof(un));
>       un.sun_family = AF_UNIX;
>       snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);
>       if (connect(sock, (struct sockaddr*)&un, sizeof(un))<  0) {
> -        fprintf(stderr, "connect(unix:%s): %s\n", path, strerror(errno));
> -        close(sock);
> -	return -1;
> +        goto err;
>       }
>
>       return sock;
> +
> +err:
> +    error_report("Can't connect to socket %s: %s",
> +                 un.sun_path, strerror(errno));
> +    if (sock>= 0) {
> +        close(sock);
> +    }
> +    return -1;
>   }

Basically, same thing here and the remaining functions.  Let's not introduce 
additional uses of error_report().

That said, I imagine you don't want to introduce a bunch of error types for 
these different things and that's probably not productive anyway.

So let's compromise and introduce a generic QERR_INTERNAL_ERROR that takes a 
single human readable string as an argument.  We can have a wrapper for it that 
also records location information in the error object.

Regards,

Anthony Liguori

  reply	other threads:[~2012-02-07 15:16 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-02-07 14:09 [Qemu-devel] [PATCH 00/19] Fix and improve chardev open error messages Markus Armbruster
2012-02-07 14:09 ` [Qemu-devel] [PATCH 01/19] Revert "qemu-char: Print strerror message on failure" and deps Markus Armbruster
2012-02-07 15:06   ` Anthony Liguori
2012-02-07 14:09 ` [Qemu-devel] [PATCH 02/19] qemu-char: Use qemu_open() to avoid leaking fds to children Markus Armbruster
2012-02-07 15:07   ` Anthony Liguori
2012-02-07 14:09 ` [Qemu-devel] [PATCH 03/19] qemu-char: Re-apply style fixes from just reverted aad04cd0 Markus Armbruster
2012-02-07 15:07   ` Anthony Liguori
2012-02-07 14:09 ` [Qemu-devel] [PATCH 04/19] qemu-char: qemu_chr_open_fd() can't fail, don't check Markus Armbruster
2012-02-07 15:24   ` Anthony Liguori
2012-02-07 14:09 ` [Qemu-devel] [PATCH 05/19] vl.c: Error locations for options using add_device_config() Markus Armbruster
2012-02-07 14:09 ` [Qemu-devel] [PATCH 06/19] gdbstub: Error locations for -gdb Markus Armbruster
2012-02-07 15:32   ` Kevin Wolf
2012-02-09 15:08     ` Markus Armbruster
2012-02-07 14:09 ` [Qemu-devel] [PATCH 07/19] sockets: Drop sockets_debug debug code Markus Armbruster
2012-02-07 14:09 ` [Qemu-devel] [PATCH 08/19] sockets: Clean up inet_listen_opts()'s convoluted bind() loop Markus Armbruster
2012-02-07 14:09 ` [Qemu-devel] [PATCH 09/19] sockets: Chardev open error reporting, sockets part Markus Armbruster
2012-02-07 15:13   ` Anthony Liguori [this message]
2012-02-09 16:05     ` Markus Armbruster
2012-02-14 17:24       ` Markus Armbruster
2012-02-14 19:05         ` Anthony Liguori
2012-02-15 13:33           ` Markus Armbruster
2012-02-22 20:28             ` Anthony Liguori
2012-02-23  8:15               ` Markus Armbruster
2012-08-29 15:15                 ` Amos Kong
2012-08-29 16:04                   ` Amos Kong
2012-09-05  2:19                     ` Amos Kong
2012-09-05 18:52                       ` Luiz Capitulino
2012-02-07 14:09 ` [Qemu-devel] [PATCH 10/19] qemu-char: Chardev open error reporting, !_WIN32 part Markus Armbruster
2012-02-07 15:52   ` Kevin Wolf
2012-02-09 15:16     ` Markus Armbruster
2012-02-09 15:39       ` Kevin Wolf
2012-02-09 16:19         ` Markus Armbruster
2012-02-09 16:31           ` Luiz Capitulino
2012-02-09 17:08             ` Markus Armbruster
2012-02-07 14:09 ` [Qemu-devel] [PATCH 11/19] qemu-char: Chardev open error reporting, _WIN32 part Markus Armbruster
2012-02-07 14:09 ` [Qemu-devel] [PATCH 12/19] qemu-char: Chardev open error reporting, tty part Markus Armbruster
2012-02-07 14:09 ` [Qemu-devel] [PATCH 13/19] qemu-char: Chardev open error reporting, parport part Markus Armbruster
2012-02-07 14:09 ` [Qemu-devel] [PATCH 14/19] console: Eliminate text_consoles[] Markus Armbruster
2012-02-07 14:09 ` [Qemu-devel] [PATCH 15/19] console: Chardev open error reporting, console part Markus Armbruster
2012-02-07 14:09 ` [Qemu-devel] [PATCH 16/19] spice-qemu-char: Chardev open error reporting, spicevmc part Markus Armbruster
2012-02-07 14:09 ` [Qemu-devel] [PATCH 17/19] baum: Chardev open error reporting, braille part Markus Armbruster
2012-02-07 14:09 ` [Qemu-devel] [PATCH 18/19] qemu-char: Chardev open error reporting, generic part Markus Armbruster
2012-02-07 14:09 ` [Qemu-devel] [PATCH 19/19] qemu-char: Fix legacy chardev syntax error reporting Markus Armbruster
2012-02-07 16:05 ` [Qemu-devel] [PATCH 00/19] Fix and improve chardev open error messages Kevin Wolf
2012-02-24 15:30 ` Anthony Liguori

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=4F313F86.7080103@us.ibm.com \
    --to=aliguori@us.ibm.com \
    --cc=armbru@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /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).