diff --git a/CMakeLists.txt b/CMakeLists.txt index cb79bfa3..bcc77451 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -508,6 +508,7 @@ if(LIBUV_BUILD_TESTS) test/test-udp-send-and-recv.c test/test-udp-send-hang-loop.c test/test-udp-send-immediate.c + test/test-udp-sendmmsg-error.c test/test-udp-send-unreachable.c test/test-udp-try-send.c test/test-uname.c diff --git a/Makefile.am b/Makefile.am index c3391c2a..754e70c4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -296,6 +296,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-udp-send-and-recv.c \ test/test-udp-send-hang-loop.c \ test/test-udp-send-immediate.c \ + test/test-udp-sendmmsg-error.c \ test/test-udp-send-unreachable.c \ test/test-udp-try-send.c \ test/test-uname.c \ diff --git a/src/unix/udp.c b/src/unix/udp.c index 7cf80ef3..508c619f 100644 --- a/src/unix/udp.c +++ b/src/unix/udp.c @@ -367,7 +367,7 @@ write_queue_drain: return; for (i = 0, q = QUEUE_HEAD(&handle->write_queue); i < pkts && q != &handle->write_queue; - ++i, q = QUEUE_HEAD(q)) { + ++i, q = QUEUE_HEAD(&handle->write_queue)) { assert(q != NULL); req = QUEUE_DATA(q, uv_udp_send_t, queue); assert(req != NULL); diff --git a/test/test-list.h b/test/test-list.h index 6146434e..58e174d1 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -180,6 +180,7 @@ TEST_DECLARE (udp_open_connect) #ifndef _WIN32 TEST_DECLARE (udp_send_unix) #endif +TEST_DECLARE (udp_sendmmsg_error) TEST_DECLARE (udp_try_send) TEST_DECLARE (pipe_bind_error_addrinuse) TEST_DECLARE (pipe_bind_error_addrnotavail) @@ -720,6 +721,7 @@ TASK_LIST_START TEST_ENTRY (udp_multicast_join) TEST_ENTRY (udp_multicast_join6) TEST_ENTRY (udp_multicast_ttl) + TEST_ENTRY (udp_sendmmsg_error) TEST_ENTRY (udp_try_send) TEST_ENTRY (udp_open) diff --git a/test/test-udp-sendmmsg-error.c b/test/test-udp-sendmmsg-error.c new file mode 100644 index 00000000..c8a411b2 --- /dev/null +++ b/test/test-udp-sendmmsg-error.c @@ -0,0 +1,75 @@ +/* Copyright libuv project and contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "task.h" + +#include +#include + +#define DATAGRAMS 6 + +static uv_udp_t client; +static uv_udp_send_t req[DATAGRAMS]; + +static int send_cb_called; +static int close_cb_called; + + +static void close_cb(uv_handle_t* handle) { + ASSERT_PTR_EQ(handle, &client); + ASSERT(uv_is_closing(handle)); + close_cb_called++; +} + + +static void send_cb(uv_udp_send_t* req, int status) { + if (status != 0) + ASSERT_EQ(status, UV_ECONNREFUSED); + + if (++send_cb_called == DATAGRAMS) + uv_close((uv_handle_t*)&client, close_cb); +} + + +TEST_IMPL(udp_sendmmsg_error) { + struct sockaddr_in addr; + uv_buf_t buf; + int i; + + ASSERT_EQ(0, uv_udp_init(uv_default_loop(), &client)); + ASSERT_EQ(0, uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); + ASSERT_EQ(0, uv_udp_connect(&client, (const struct sockaddr*)&addr)); + + buf = uv_buf_init("TEST", 4); + for (i = 0; i < DATAGRAMS; ++i) + ASSERT_EQ(0, uv_udp_send(&req[i], &client, &buf, 1, NULL, send_cb)); + + uv_run(uv_default_loop(), UV_RUN_DEFAULT); + + ASSERT_EQ(1, close_cb_called); + ASSERT_EQ(DATAGRAMS, send_cb_called); + + ASSERT_EQ(0, client.send_queue_size); + + MAKE_VALGRIND_HAPPY(); + return 0; +}