mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-03 17:56:17 +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
|
* notified of a %G_IO_OUT condition. (On Windows in particular, this is
|
||||||
* very common due to the way the underlying APIs work.)
|
* 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
|
* 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
|
* 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)
|
#if !defined (G_OS_WIN32) && defined (HAVE_SENDMMSG)
|
||||||
{
|
{
|
||||||
struct mmsghdr *msgvec;
|
struct mmsghdr *msgvec;
|
||||||
gint i, num_sent, result, max_sent;
|
gint i, num_sent;
|
||||||
|
|
||||||
#ifdef UIO_MAXIOV
|
#ifdef UIO_MAXIOV
|
||||||
#define MAX_NUM_MESSAGES UIO_MAXIOV
|
#define MAX_NUM_MESSAGES UIO_MAXIOV
|
||||||
@ -4383,9 +4385,7 @@ g_socket_send_messages_with_timeout (GSocket *socket,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
num_sent = result = 0;
|
for (num_sent = 0; num_sent < num_messages;)
|
||||||
max_sent = num_messages;
|
|
||||||
while (num_sent < num_messages)
|
|
||||||
{
|
{
|
||||||
gint ret;
|
gint ret;
|
||||||
|
|
||||||
@ -4418,32 +4418,22 @@ g_socket_send_messages_with_timeout (GSocket *socket,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num_sent > 0 &&
|
/* If any messages were successfully sent, do not error. */
|
||||||
(errsv == EWOULDBLOCK ||
|
if (num_sent > 0)
|
||||||
errsv == EAGAIN))
|
|
||||||
{
|
|
||||||
max_sent = num_sent;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
socket_set_error_lazy (error, errsv, _("Error sending message: %s"));
|
socket_set_error_lazy (error, errsv, _("Error sending message: %s"));
|
||||||
|
|
||||||
/* we have to iterate over all messages below now, because we don't
|
return -1;
|
||||||
* know where between num_sent and num_messages the error occured */
|
|
||||||
max_sent = num_messages;
|
|
||||||
|
|
||||||
result = -1;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
num_sent += ret;
|
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;
|
messages[i].bytes_sent = msgvec[i].msg_len;
|
||||||
|
|
||||||
return result;
|
return num_sent;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
|
@ -703,14 +703,31 @@ test_ip_sync_dgram (GSocketFamily family)
|
|||||||
m[1].bytes_sent = 0;
|
m[1].bytes_sent = 0;
|
||||||
m[2].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;
|
m[1].address = NULL;
|
||||||
len = g_socket_send_messages (client, m, G_N_ELEMENTS (m), 0, NULL, &error);
|
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_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
|
||||||
g_clear_error (&error);
|
g_clear_error (&error);
|
||||||
g_assert_cmpint (len, ==, -1);
|
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[1].bytes_sent, ==, 0);
|
||||||
g_assert_cmpint (m[2].bytes_sent, ==, 0);
|
g_assert_cmpint (m[2].bytes_sent, ==, 0);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user