mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-24 13:06:14 +01:00
gsocket: Fix error behaviour of g_socket_send_messages()
If an error in the underlying sendmmsg() syscall occurs after successfully sending one or more messages, g_socket_send_messages() should return the number of messages successfully sent, rather than an error. This mirrors the documented sendmmsg() behaviour. This is a slight behaviour change for g_socket_send_messages(), but as it relaxes the error reporting (reporting errors in fewer situations than before), it should not cause problems. https://bugzilla.gnome.org/show_bug.cgi?id=751924
This commit is contained in:
parent
f62cbfc022
commit
1086507e75
@ -4295,7 +4295,9 @@ g_socket_send_message (GSocket *socket,
|
||||
* notified of a %G_IO_OUT condition. (On Windows in particular, this is
|
||||
* very common due to the way the underlying APIs work.)
|
||||
*
|
||||
* On error -1 is returned and @error is set accordingly.
|
||||
* On error -1 is returned and @error is set accordingly. An error will only
|
||||
* be returned if zero messages could be sent; otherwise the number of messages
|
||||
* successfully sent before the error will be returned.
|
||||
*
|
||||
* Returns: number of messages sent, or -1 on error. Note that the number of
|
||||
* messages sent may be smaller than @num_messages if the socket is
|
||||
@ -4351,7 +4353,7 @@ g_socket_send_messages_with_timeout (GSocket *socket,
|
||||
#if !defined (G_OS_WIN32) && defined (HAVE_SENDMMSG)
|
||||
{
|
||||
struct mmsghdr *msgvec;
|
||||
gint i, num_sent, result, max_sent;
|
||||
gint i, num_sent;
|
||||
|
||||
#ifdef UIO_MAXIOV
|
||||
#define MAX_NUM_MESSAGES UIO_MAXIOV
|
||||
@ -4383,9 +4385,7 @@ g_socket_send_messages_with_timeout (GSocket *socket,
|
||||
}
|
||||
}
|
||||
|
||||
num_sent = result = 0;
|
||||
max_sent = num_messages;
|
||||
while (num_sent < num_messages)
|
||||
for (num_sent = 0; num_sent < num_messages;)
|
||||
{
|
||||
gint ret;
|
||||
|
||||
@ -4418,32 +4418,22 @@ g_socket_send_messages_with_timeout (GSocket *socket,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (num_sent > 0 &&
|
||||
(errsv == EWOULDBLOCK ||
|
||||
errsv == EAGAIN))
|
||||
{
|
||||
max_sent = num_sent;
|
||||
break;
|
||||
}
|
||||
/* If any messages were successfully sent, do not error. */
|
||||
if (num_sent > 0)
|
||||
break;
|
||||
|
||||
socket_set_error_lazy (error, errsv, _("Error sending message: %s"));
|
||||
|
||||
/* we have to iterate over all messages below now, because we don't
|
||||
* know where between num_sent and num_messages the error occured */
|
||||
max_sent = num_messages;
|
||||
|
||||
result = -1;
|
||||
break;
|
||||
return -1;
|
||||
}
|
||||
|
||||
num_sent += ret;
|
||||
result = num_sent;
|
||||
}
|
||||
|
||||
for (i = 0; i < max_sent; ++i)
|
||||
for (i = 0; i < num_sent; ++i)
|
||||
messages[i].bytes_sent = msgvec[i].msg_len;
|
||||
|
||||
return result;
|
||||
return num_sent;
|
||||
}
|
||||
#else
|
||||
{
|
||||
|
@ -703,14 +703,31 @@ test_ip_sync_dgram (GSocketFamily family)
|
||||
m[1].bytes_sent = 0;
|
||||
m[2].bytes_sent = 0;
|
||||
|
||||
/* now try to generate an error by omitting the destination address on [1] */
|
||||
/* now try to generate an early return by omitting the destination address on [1] */
|
||||
m[1].address = NULL;
|
||||
len = g_socket_send_messages (client, m, G_N_ELEMENTS (m), 0, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert_cmpint (len, ==, 1);
|
||||
|
||||
g_assert_cmpint (m[0].bytes_sent, ==, 3);
|
||||
g_assert_cmpint (m[1].bytes_sent, ==, 0);
|
||||
g_assert_cmpint (m[2].bytes_sent, ==, 0);
|
||||
|
||||
/* reset since we're re-using the message structs */
|
||||
m[0].bytes_sent = 0;
|
||||
m[1].bytes_sent = 0;
|
||||
m[2].bytes_sent = 0;
|
||||
|
||||
/* now try to generate an error by omitting all destination addresses */
|
||||
m[0].address = NULL;
|
||||
m[1].address = NULL;
|
||||
m[2].address = NULL;
|
||||
len = g_socket_send_messages (client, m, G_N_ELEMENTS (m), 0, NULL, &error);
|
||||
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
|
||||
g_clear_error (&error);
|
||||
g_assert_cmpint (len, ==, -1);
|
||||
|
||||
g_assert_cmpint (m[0].bytes_sent, ==, 3);
|
||||
g_assert_cmpint (m[0].bytes_sent, ==, 0);
|
||||
g_assert_cmpint (m[1].bytes_sent, ==, 0);
|
||||
g_assert_cmpint (m[2].bytes_sent, ==, 0);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user