diff options
author | Dan Winship <danw@gnome.org> | 2011-11-14 18:27:34 -0500 |
---|---|---|
committer | Dan Winship <danw@gnome.org> | 2011-11-14 18:31:21 -0500 |
commit | 74dad004d143a2d3fbe4171d20e57cc9942ad89d (patch) | |
tree | 60df9687310d5f9a8d76d31d121215c2149bec83 /gio/gunixinputstream.c | |
parent | 29f786851d9fb8c8229161087e55254e379ef6e7 (diff) |
GUnixInput/OutputStream: fix blocking methods to always block
Previously, if you created a GUnixInputStream or GUnixOutputStream
from a non-blocking file descriptor, it might sometimes return
G_IO_ERROR_WOULD_BLOCK from g_input_stream_read/g_output_stream_write,
which is wrong. Fix that. (Use the GPollableInput/OutputStream methods
if you want non-blocking I/O.)
Also, add a test for this to gio/tests/unix-streams.
Also, fix the GError messages to say "Error reading from file
descriptor", etc instead of "Error reading from unix" (which was
presumably from a bad search and replace job).
https://bugzilla.gnome.org/show_bug.cgi?id=626866
Diffstat (limited to 'gio/gunixinputstream.c')
-rw-r--r-- | gio/gunixinputstream.c | 48 |
1 files changed, 28 insertions, 20 deletions
diff --git a/gio/gunixinputstream.c b/gio/gunixinputstream.c index c2137280c..3d5f93806 100644 --- a/gio/gunixinputstream.c +++ b/gio/gunixinputstream.c @@ -361,21 +361,27 @@ g_unix_input_stream_read (GInputStream *stream, GError **error) { GUnixInputStream *unix_stream; - gssize res; + gssize res = -1; GPollFD poll_fds[2]; + int nfds; int poll_ret; unix_stream = G_UNIX_INPUT_STREAM (stream); + poll_fds[0].fd = unix_stream->priv->fd; + poll_fds[0].events = G_IO_IN; if (unix_stream->priv->is_pipe_or_socket && g_cancellable_make_pollfd (cancellable, &poll_fds[1])) + nfds = 2; + else + nfds = 1; + + while (1) { - poll_fds[0].fd = unix_stream->priv->fd; - poll_fds[0].events = G_IO_IN; + poll_fds[0].revents = poll_fds[1].revents = 0; do - poll_ret = g_poll (poll_fds, 2, -1); + poll_ret = g_poll (poll_fds, nfds, -1); while (poll_ret == -1 && errno == EINTR); - g_cancellable_release_fd (cancellable); if (poll_ret == -1) { @@ -383,33 +389,35 @@ g_unix_input_stream_read (GInputStream *stream, g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), - _("Error reading from unix: %s"), + _("Error reading from file descriptor: %s"), g_strerror (errsv)); - return -1; + break; } - } - while (1) - { if (g_cancellable_set_error_if_cancelled (cancellable, error)) - return -1; + break; + + if (!poll_fds[0].revents) + continue; + res = read (unix_stream->priv->fd, buffer, count); if (res == -1) { int errsv = errno; - if (errsv == EINTR) + if (errsv == EINTR || errsv == EAGAIN) continue; - + g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), - _("Error reading from unix: %s"), + _("Error reading from file descriptor: %s"), g_strerror (errsv)); } - + break; } + g_cancellable_release_fd (cancellable); return res; } @@ -436,7 +444,7 @@ g_unix_input_stream_close (GInputStream *stream, g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), - _("Error closing unix: %s"), + _("Error closing file descriptor: %s"), g_strerror (errsv)); } break; @@ -476,12 +484,12 @@ read_async_cb (int fd, { int errsv = errno; - if (errsv == EINTR) - continue; + if (errsv == EINTR || errsv == EAGAIN) + return TRUE; g_set_error (&error, G_IO_ERROR, g_io_error_from_errno (errsv), - _("Error reading from unix: %s"), + _("Error reading from file descriptor: %s"), g_strerror (errsv)); } break; @@ -631,7 +639,7 @@ close_async_cb (CloseAsyncData *data) g_set_error (&error, G_IO_ERROR, g_io_error_from_errno (errsv), - _("Error closing unix: %s"), + _("Error closing file descriptor: %s"), g_strerror (errsv)); } break; |