aboutsummaryrefslogtreecommitdiffstats
path: root/src/qmi-device.c
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@lanedo.com>2012-05-03 14:53:56 +0200
committerAleksander Morgado <aleksander@lanedo.com>2012-07-03 16:08:49 +0200
commita4347d4d226da32f0b18c2e263e6f0cf7d0bb691 (patch)
treec92f043562d97fd7d27b5f01bcac4ba54afaba07 /src/qmi-device.c
parenta580711cdf974d1b695388c07f2c6c993ca15b99 (diff)
downloadexternal_libqmi-a4347d4d226da32f0b18c2e263e6f0cf7d0bb691.zip
external_libqmi-a4347d4d226da32f0b18c2e263e6f0cf7d0bb691.tar.gz
external_libqmi-a4347d4d226da32f0b18c2e263e6f0cf7d0bb691.tar.bz2
device: handle EAGAIN errors when writing to the channel
If the non-blocking socket's write buffers are full, the non-blocking write may fail with EAGAIN errors, which we should just treat as a request to retry the write.
Diffstat (limited to 'src/qmi-device.c')
-rw-r--r--src/qmi-device.c44
1 files changed, 32 insertions, 12 deletions
diff --git a/src/qmi-device.c b/src/qmi-device.c
index adde6f2..b4edbce 100644
--- a/src/qmi-device.c
+++ b/src/qmi-device.c
@@ -1156,6 +1156,7 @@ qmi_device_command (QmiDevice *self,
gconstpointer raw_message;
gsize raw_message_len;
gsize written;
+ GIOStatus write_status;
g_return_if_fail (QMI_IS_DEVICE (self));
g_return_if_fail (message != NULL);
@@ -1209,18 +1210,37 @@ qmi_device_command (QmiDevice *self,
device_store_transaction (self, tr, timeout);
written = 0;
- if (g_io_channel_write_chars (self->priv->iochannel,
- raw_message,
- (gssize)raw_message_len,
- &written,
- &error) != G_IO_STATUS_NORMAL) {
- g_prefix_error (&error, "Cannot write message: ");
-
- /* Match transaction so that we remove it from our tracking table */
- tr = device_match_transaction (self, message);
- transaction_complete_and_free (tr, NULL, error);
- g_error_free (error);
- return;
+ write_status = G_IO_STATUS_AGAIN;
+ while (write_status == G_IO_STATUS_AGAIN) {
+ write_status = g_io_channel_write_chars (self->priv->iochannel,
+ raw_message,
+ (gssize)raw_message_len,
+ &written,
+ &error);
+ switch (write_status) {
+ case G_IO_STATUS_ERROR:
+ g_prefix_error (&error, "Cannot write message: ");
+
+ /* Match transaction so that we remove it from our tracking table */
+ tr = device_match_transaction (self, message);
+ transaction_complete_and_free (tr, NULL, error);
+ g_error_free (error);
+ return;
+
+ case G_IO_STATUS_EOF:
+ /* We shouldn't get EOF when writing */
+ g_assert_not_reached ();
+ break;
+
+ case G_IO_STATUS_NORMAL:
+ /* All good, we'll exit the loop now */
+ break;
+
+ case G_IO_STATUS_AGAIN:
+ /* We're in a non-blocking channel and therefore we're up to receive
+ * EAGAIN; just retry in this case. TODO: in an idle? */
+ break;
+ }
}
/* Just return, we'll get response asynchronously */