[Spice-devel] [PATCH 4/5] server: introduce dispatcher

Paolo Bonzini pbonzini at redhat.com
Mon Nov 7 00:28:34 PST 2011


On 11/06/2011 05:49 PM, Alon Levy wrote:
> +    while (read_size<  size) {
> +        ret = read(fd, buf + read_size, size - read_size);
> +        if (ret == -1) {
> +            if (errno != EINTR) {
> +                if (errno == EAGAIN&&  !block) {
> +                    return 0;
> +                }
> +                return -1;
> +            }
> +            continue;
> +        }
> +        if (ret == 0) {
> +            if (block) {
> +                red_error("broken pipe on read");
> +                return -1;

No, broken pipe on read will return 0 for non-blocking too.

The if should be removed, and the else branch below should be moved to 
errno == EAGAIN && block.

That is,

    if (fd_set_blocking(fd, block) == -1) {
        return -1;
    }
    while (read_size < size) {
        ret = read(fd, buf + read_size, size - read_size);
        if (ret == -1) {
            if (errno == EINTR) {
                continue;
            }
            if (errno == EAGAIN) {
                if (read_size == 0) {
                    /* Nothing read so far, return 0.  */
                    return 0;
                }
                if (fd_set_blocking(fd, 1) == -1) {
                    return -1;
                }
                continue;
            }
            return -1;
        }
        if (ret == 0) {
            red_error("broken pipe on read");
            errno = ECONNRESET; /* example */
            return -1;
        }
        read_size += ret;

> +/*
> + * write_safe
> + * @return -1 for error, otherwise number of written bytes. may be zero.
> + */
> +static int write_safe(int fd, void *buf, size_t size)
> +{
> +    int write_size = 0;
            ^^^^^

Should be "written" (the "read" in read_size is pronounced "red", not 
"reed").

> +    int ret;
> +
> +    while (write_size<  size) {
> +        ret = write(fd, buf + write_size, size - write_size);
> +        if (ret == -1) {
> +            if (errno != EINTR) {
> +                return -1;
> +            }
> +            continue;
> +        }
> +        if (ret == 0) {
> +            red_error("broken pipe on write");
> +            return -1;

Broken pipe on write will return EPIPE or raise SIGPIPE (likely the 
former).  You can just remove the if altogether here.

However, you likely want to handle EAGAIN like in read_safe.  Perhaps 
you need a block argument to write_safe as well.  If not, O_NONBLOCK 
applies to both read and write, so you should set it to a known 
invariant value---either at the end of read_safe, or at the beginning of 
write_safe.

Alternatively, instead of toggling the blocking flag, you can always 
leave it set and use a single poll system call in the !block case.  If 
the descriptor is not readable (resp. writeable) you return 0 immediately.

Paolo


More information about the Spice-devel mailing list