mirror of
				https://gitlab.gnome.org/GNOME/glib.git
				synced 2025-10-31 00:12:19 +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:
		| @@ -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); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user