Home | History | Annotate | Line # | Download | only in test
      1 /* Copyright Joyent, Inc. and other Node 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 
     23 /* This test does not pretend to be cross-platform. */
     24 #ifndef _WIN32
     25 
     26 #include "uv.h"
     27 #include "task.h"
     28 
     29 #include <errno.h>
     30 #include <signal.h>
     31 #include <stdarg.h>
     32 #include <stdio.h>
     33 #include <stdlib.h>
     34 #include <string.h>
     35 #include <unistd.h>
     36 
     37 /* The value of NUM_SIGNAL_HANDLING_THREADS is not arbitrary; it needs to be a
     38  * multiple of three for reasons that will become clear when you scroll down.
     39  * We're basically creating three different thread groups.  The total needs
     40  * to be divisible by three in order for the numbers in the final check to
     41  * match up.
     42  */
     43 #define NUM_SIGNAL_HANDLING_THREADS 24
     44 #define NUM_LOOP_CREATING_THREADS 10
     45 
     46 enum signal_action {
     47   ONLY_SIGUSR1,
     48   ONLY_SIGUSR2,
     49   SIGUSR1_AND_SIGUSR2
     50 };
     51 
     52 static uv_sem_t sem;
     53 static uv_mutex_t lock;
     54 static int stop = 0;
     55 
     56 static int signal1_cb_counter = 0;
     57 static int signal2_cb_counter = 0;
     58 static int loop_creation_counter = 0;
     59 
     60 
     61 static void increment_counter(int* counter) {
     62   uv_mutex_lock(&lock);
     63   ++(*counter);
     64   uv_mutex_unlock(&lock);
     65 }
     66 
     67 
     68 static void signal1_cb(uv_signal_t* handle, int signum) {
     69   ASSERT_EQ(signum, SIGUSR1);
     70   increment_counter(&signal1_cb_counter);
     71   uv_signal_stop(handle);
     72 }
     73 
     74 
     75 static void signal2_cb(uv_signal_t* handle, int signum) {
     76   ASSERT_EQ(signum, SIGUSR2);
     77   increment_counter(&signal2_cb_counter);
     78   uv_signal_stop(handle);
     79 }
     80 
     81 
     82 static void signal_handling_worker(void* context) {
     83   enum signal_action action;
     84   uv_signal_t signal1a;
     85   uv_signal_t signal1b;
     86   uv_signal_t signal2;
     87   uv_loop_t loop;
     88   int r;
     89 
     90   action = (enum signal_action) (uintptr_t) context;
     91 
     92   ASSERT_OK(uv_loop_init(&loop));
     93 
     94   /* Setup the signal watchers and start them. */
     95   if (action == ONLY_SIGUSR1 || action == SIGUSR1_AND_SIGUSR2) {
     96     r = uv_signal_init(&loop, &signal1a);
     97     ASSERT_OK(r);
     98     r = uv_signal_start(&signal1a, signal1_cb, SIGUSR1);
     99     ASSERT_OK(r);
    100     r = uv_signal_init(&loop, &signal1b);
    101     ASSERT_OK(r);
    102     r = uv_signal_start(&signal1b, signal1_cb, SIGUSR1);
    103     ASSERT_OK(r);
    104   }
    105 
    106   if (action == ONLY_SIGUSR2 || action == SIGUSR1_AND_SIGUSR2) {
    107     r = uv_signal_init(&loop, &signal2);
    108     ASSERT_OK(r);
    109     r = uv_signal_start(&signal2, signal2_cb, SIGUSR2);
    110     ASSERT_OK(r);
    111   }
    112 
    113   /* Signal watchers are now set up. */
    114   uv_sem_post(&sem);
    115 
    116   /* Wait for all signals. The signal callbacks stop the watcher, so uv_run
    117    * will return when all signal watchers caught a signal.
    118    */
    119   r = uv_run(&loop, UV_RUN_DEFAULT);
    120   ASSERT_OK(r);
    121 
    122   /* Restart the signal watchers. */
    123   if (action == ONLY_SIGUSR1 || action == SIGUSR1_AND_SIGUSR2) {
    124     r = uv_signal_start(&signal1a, signal1_cb, SIGUSR1);
    125     ASSERT_OK(r);
    126     r = uv_signal_start(&signal1b, signal1_cb, SIGUSR1);
    127     ASSERT_OK(r);
    128   }
    129 
    130   if (action == ONLY_SIGUSR2 || action == SIGUSR1_AND_SIGUSR2) {
    131     r = uv_signal_start(&signal2, signal2_cb, SIGUSR2);
    132     ASSERT_OK(r);
    133   }
    134 
    135   /* Wait for signals once more. */
    136   uv_sem_post(&sem);
    137 
    138   r = uv_run(&loop, UV_RUN_DEFAULT);
    139   ASSERT_OK(r);
    140 
    141   /* Close the watchers. */
    142   if (action == ONLY_SIGUSR1 || action == SIGUSR1_AND_SIGUSR2) {
    143     uv_close((uv_handle_t*) &signal1a, NULL);
    144     uv_close((uv_handle_t*) &signal1b, NULL);
    145   }
    146 
    147   if (action == ONLY_SIGUSR2 || action == SIGUSR1_AND_SIGUSR2) {
    148     uv_close((uv_handle_t*) &signal2, NULL);
    149   }
    150 
    151   /* Wait for the signal watchers to close. */
    152   r = uv_run(&loop, UV_RUN_DEFAULT);
    153   ASSERT_OK(r);
    154 
    155   uv_loop_close(&loop);
    156 }
    157 
    158 
    159 static void signal_unexpected_cb(uv_signal_t* handle, int signum) {
    160   ASSERT(0 && "signal_unexpected_cb should never be called");
    161 }
    162 
    163 
    164 static void loop_creating_worker(void* context) {
    165   int done;
    166 
    167   (void) context;
    168 
    169   do {
    170     uv_loop_t *loop;
    171     uv_signal_t signal;
    172     int r;
    173 
    174     loop = malloc(sizeof(*loop));
    175     ASSERT_NOT_NULL(loop);
    176     ASSERT_OK(uv_loop_init(loop));
    177 
    178     r = uv_signal_init(loop, &signal);
    179     ASSERT_OK(r);
    180 
    181     r = uv_signal_start(&signal, signal_unexpected_cb, SIGTERM);
    182     ASSERT_OK(r);
    183 
    184     uv_close((uv_handle_t*) &signal, NULL);
    185 
    186     r = uv_run(loop, UV_RUN_DEFAULT);
    187     ASSERT_OK(r);
    188 
    189     uv_loop_close(loop);
    190     free(loop);
    191 
    192     increment_counter(&loop_creation_counter);
    193 
    194     uv_mutex_lock(&lock);
    195     done = stop;
    196     uv_mutex_unlock(&lock);
    197   } while (!done);
    198 }
    199 
    200 
    201 TEST_IMPL(signal_multiple_loops) {
    202 #if defined(__CYGWIN__) || defined(__MSYS__)
    203   /* FIXME: This test needs more investigation.  Somehow the `read` in
    204      uv__signal_lock fails spuriously with EACCES or even EAGAIN even
    205      though it is supposed to be blocking.  Also the test hangs during
    206      thread setup occasionally.  */
    207   RETURN_SKIP("FIXME: This test needs more investigation on Cygwin");
    208 #endif
    209 /* TODO(gengjiawen): Fix test on QEMU. */
    210 #if defined(__QEMU__)
    211   /* See https://github.com/libuv/libuv/issues/2859 */
    212   RETURN_SKIP("QEMU's signal emulation code is notoriously tricky");
    213 #endif
    214 #if defined(__ASAN__) || defined(__MSAN__)
    215   /* See https://github.com/libuv/libuv/issues/3956 */
    216   RETURN_SKIP("Test is too slow to run under ASan or MSan");
    217 #endif
    218 #if defined(__TSAN__)
    219   /* ThreadSanitizer complains - likely legitimately - about data races
    220    * in uv__signal_compare() in src/unix/signal.c but that's pre-existing.
    221    */
    222   RETURN_SKIP("Fix test under ThreadSanitizer");
    223 #endif
    224   uv_thread_t loop_creating_threads[NUM_LOOP_CREATING_THREADS];
    225   uv_thread_t signal_handling_threads[NUM_SIGNAL_HANDLING_THREADS];
    226   enum signal_action action;
    227   sigset_t sigset;
    228   int i;
    229   int r;
    230 
    231   r = uv_sem_init(&sem, 0);
    232   ASSERT_OK(r);
    233 
    234   r = uv_mutex_init(&lock);
    235   ASSERT_OK(r);
    236 
    237   /* Create a couple of threads that create a destroy loops continuously. */
    238   for (i = 0; i < NUM_LOOP_CREATING_THREADS; i++) {
    239     r = uv_thread_create(&loop_creating_threads[i],
    240                          loop_creating_worker,
    241                          NULL);
    242     ASSERT_OK(r);
    243   }
    244 
    245   /* Create a couple of threads that actually handle signals. */
    246   for (i = 0; i < NUM_SIGNAL_HANDLING_THREADS; i++) {
    247     switch (i % 3) {
    248       case 0: action = ONLY_SIGUSR1; break;
    249       case 1: action = ONLY_SIGUSR2; break;
    250       case 2: action = SIGUSR1_AND_SIGUSR2; break;
    251     }
    252 
    253     r = uv_thread_create(&signal_handling_threads[i],
    254                          signal_handling_worker,
    255                          (void*) (uintptr_t) action);
    256     ASSERT_OK(r);
    257   }
    258 
    259   /* Wait until all threads have started and set up their signal watchers. */
    260   for (i = 0; i < NUM_SIGNAL_HANDLING_THREADS; i++)
    261     uv_sem_wait(&sem);
    262 
    263   r = kill(getpid(), SIGUSR1);
    264   ASSERT_OK(r);
    265   r = kill(getpid(), SIGUSR2);
    266   ASSERT_OK(r);
    267 
    268   /* Wait for all threads to handle these signals. */
    269   for (i = 0; i < NUM_SIGNAL_HANDLING_THREADS; i++)
    270     uv_sem_wait(&sem);
    271 
    272   /* Block all signals to this thread, so we are sure that from here the signal
    273    * handler runs in another thread. This is more likely to catch thread and
    274    * signal safety issues if there are any.
    275    */
    276   sigfillset(&sigset);
    277   pthread_sigmask(SIG_SETMASK, &sigset, NULL);
    278 
    279   r = kill(getpid(), SIGUSR1);
    280   ASSERT_OK(r);
    281   r = kill(getpid(), SIGUSR2);
    282   ASSERT_OK(r);
    283 
    284   /* Wait for all signal handling threads to exit. */
    285   for (i = 0; i < NUM_SIGNAL_HANDLING_THREADS; i++) {
    286     r = uv_thread_join(&signal_handling_threads[i]);
    287     ASSERT_OK(r);
    288   }
    289 
    290   /* Tell all loop creating threads to stop. */
    291   uv_mutex_lock(&lock);
    292   stop = 1;
    293   uv_mutex_unlock(&lock);
    294 
    295   /* Wait for all loop creating threads to exit. */
    296   for (i = 0; i < NUM_LOOP_CREATING_THREADS; i++) {
    297     r = uv_thread_join(&loop_creating_threads[i]);
    298     ASSERT_OK(r);
    299   }
    300 
    301   uv_sem_destroy(&sem);
    302   printf("signal1_cb calls: %d\n", signal1_cb_counter);
    303   printf("signal2_cb calls: %d\n", signal2_cb_counter);
    304   printf("loops created and destroyed: %d\n", loop_creation_counter);
    305 
    306   /* The division by three reflects the fact that we spawn three different
    307    * thread groups of (NUM_SIGNAL_HANDLING_THREADS / 3) threads each.
    308    */
    309   ASSERT_EQ(signal1_cb_counter, 8 * (NUM_SIGNAL_HANDLING_THREADS / 3));
    310   ASSERT_EQ(signal2_cb_counter, 4 * (NUM_SIGNAL_HANDLING_THREADS / 3));
    311 
    312   /* We don't know exactly how much loops will be created and destroyed, but at
    313    * least there should be 1 for every loop creating thread.
    314    */
    315   ASSERT_GE(loop_creation_counter, NUM_LOOP_CREATING_THREADS);
    316 
    317   MAKE_VALGRIND_HAPPY(uv_default_loop());
    318   return 0;
    319 }
    320 
    321 #else
    322 
    323 typedef int file_has_no_tests; /* ISO C forbids an empty translation unit. */
    324 
    325 #endif /* !_WIN32 */
    326