Home | History | Annotate | Line # | Download | only in test
      1 /* Copyright Bert Belder, and other libuv contributors. All rights reserved.
      2  *
      3  * Permission is hereby granted, free of charge, to any person obtaining a copy
      4  * of this software and associated documentation files (the "Software"), to
      5  * deal in the Software without restriction, including without limitation the
      6  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
      7  * sell copies of the Software, and to permit persons to whom the Software is
      8  * furnished to do so, subject to the following conditions:
      9  *
     10  * The above copyright notice and this permission notice shall be included in
     11  * all copies or substantial portions of the Software.
     12  *
     13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     18  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     19  * IN THE SOFTWARE.
     20  */
     21 
     22 #include <errno.h>
     23 #include <stdio.h>
     24 
     25 #include "uv.h"
     26 #include "task.h"
     27 
     28 #ifdef _MSC_VER  /* msvc */
     29 # define NO_INLINE __declspec(noinline)
     30 #else  /* gcc */
     31 # define NO_INLINE __attribute__ ((noinline))
     32 #endif
     33 
     34 #ifdef _WIN32
     35 static uv_os_sock_t sock;
     36 static uv_poll_t handle;
     37 static int close_cb_called = 0;
     38 
     39 
     40 static void close_cb(uv_handle_t* h) {
     41   close_cb_called++;
     42 }
     43 
     44 
     45 static void poll_cb(uv_poll_t* h, int status, int events) {
     46   ASSERT(0 && "should never get here");
     47 }
     48 
     49 
     50 static void NO_INLINE close_socket_and_verify_stack(void) {
     51   const uint32_t MARKER = 0xDEADBEEF;
     52   const int VERIFY_AFTER = 10; /* ms */
     53   int r;
     54 
     55   volatile uint32_t data[65536];
     56   size_t i;
     57 
     58   for (i = 0; i < ARRAY_SIZE(data); i++)
     59     data[i] = MARKER;
     60 
     61   r = closesocket(sock);
     62   ASSERT_OK(r);
     63 
     64   uv_sleep(VERIFY_AFTER);
     65 
     66   for (i = 0; i < ARRAY_SIZE(data); i++)
     67     ASSERT_EQ(data[i], MARKER);
     68 }
     69 #endif
     70 
     71 
     72 TEST_IMPL(poll_close_doesnt_corrupt_stack) {
     73 #ifndef _WIN32
     74   RETURN_SKIP("Test only relevant on Windows");
     75 #else
     76   struct WSAData wsa_data;
     77   int r;
     78   unsigned long on;
     79   struct sockaddr_in addr;
     80 
     81   r = WSAStartup(MAKEWORD(2, 2), &wsa_data);
     82   ASSERT_OK(r);
     83 
     84   sock = socket(AF_INET, SOCK_STREAM, 0);
     85   ASSERT_NE(sock, INVALID_SOCKET);
     86   on = 1;
     87   r = ioctlsocket(sock, FIONBIO, &on);
     88   ASSERT_OK(r);
     89 
     90   r = uv_ip4_addr("127.0.0.1", TEST_PORT, &addr);
     91   ASSERT_OK(r);
     92 
     93   r = connect(sock, (const struct sockaddr*) &addr, sizeof addr);
     94   ASSERT(r);
     95   ASSERT_EQ(WSAGetLastError(), WSAEWOULDBLOCK);
     96 
     97   r = uv_poll_init_socket(uv_default_loop(), &handle, sock);
     98   ASSERT_OK(r);
     99   r = uv_poll_start(&handle, UV_READABLE | UV_WRITABLE, poll_cb);
    100   ASSERT_OK(r);
    101 
    102   uv_close((uv_handle_t*) &handle, close_cb);
    103 
    104   close_socket_and_verify_stack();
    105 
    106   r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
    107   ASSERT_OK(r);
    108 
    109   ASSERT_EQ(1, close_cb_called);
    110 
    111   MAKE_VALGRIND_HAPPY(uv_default_loop());
    112   return 0;
    113 #endif
    114 }
    115