1 1.1 christos /* Copyright Joyent, Inc. and other Node contributors. All rights reserved. 2 1.1 christos * 3 1.1 christos * Permission is hereby granted, free of charge, to any person obtaining a copy 4 1.1 christos * of this software and associated documentation files (the "Software"), to 5 1.1 christos * deal in the Software without restriction, including without limitation the 6 1.1 christos * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7 1.1 christos * sell copies of the Software, and to permit persons to whom the Software is 8 1.1 christos * furnished to do so, subject to the following conditions: 9 1.1 christos * 10 1.1 christos * The above copyright notice and this permission notice shall be included in 11 1.1 christos * all copies or substantial portions of the Software. 12 1.1 christos * 13 1.1 christos * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 1.1 christos * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 1.1 christos * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 1.1 christos * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 1.1 christos * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 1.1 christos * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19 1.1 christos * IN THE SOFTWARE. 20 1.1 christos */ 21 1.1 christos 22 1.1 christos #include "uv.h" 23 1.1 christos #include "task.h" 24 1.1 christos 25 1.1 christos #ifndef _WIN32 26 1.1 christos #include <unistd.h> 27 1.1 christos #endif 28 1.1 christos 29 1.1 christos TEST_IMPL(kill_invalid_signum) { 30 1.1 christos uv_pid_t pid; 31 1.1 christos 32 1.1 christos pid = uv_os_getpid(); 33 1.1 christos 34 1.1.1.2 christos ASSERT_EQ(uv_kill(pid, -1), UV_EINVAL); 35 1.1 christos #ifdef _WIN32 36 1.1 christos /* NSIG is not available on all platforms. */ 37 1.1.1.2 christos ASSERT_EQ(uv_kill(pid, NSIG), UV_EINVAL); 38 1.1 christos #endif 39 1.1.1.2 christos ASSERT_EQ(uv_kill(pid, 4096), UV_EINVAL); 40 1.1 christos 41 1.1.1.2 christos MAKE_VALGRIND_HAPPY(uv_default_loop()); 42 1.1 christos return 0; 43 1.1 christos } 44 1.1 christos 45 1.1 christos /* For Windows we test only signum handling */ 46 1.1 christos #ifdef _WIN32 47 1.1 christos static void signum_test_cb(uv_signal_t* handle, int signum) { 48 1.1 christos FATAL("signum_test_cb should not be called"); 49 1.1 christos } 50 1.1 christos 51 1.1 christos TEST_IMPL(win32_signum_number) { 52 1.1 christos uv_signal_t signal; 53 1.1 christos uv_loop_t* loop; 54 1.1 christos 55 1.1 christos loop = uv_default_loop(); 56 1.1 christos uv_signal_init(loop, &signal); 57 1.1 christos 58 1.1.1.2 christos ASSERT_EQ(uv_signal_start(&signal, signum_test_cb, 0), UV_EINVAL); 59 1.1.1.2 christos ASSERT_OK(uv_signal_start(&signal, signum_test_cb, SIGINT)); 60 1.1.1.2 christos ASSERT_OK(uv_signal_start(&signal, signum_test_cb, SIGBREAK)); 61 1.1.1.2 christos ASSERT_OK(uv_signal_start(&signal, signum_test_cb, SIGHUP)); 62 1.1.1.2 christos ASSERT_OK(uv_signal_start(&signal, signum_test_cb, SIGWINCH)); 63 1.1.1.2 christos ASSERT_OK(uv_signal_start(&signal, signum_test_cb, SIGILL)); 64 1.1.1.2 christos ASSERT_OK(uv_signal_start(&signal, signum_test_cb, SIGABRT_COMPAT)); 65 1.1.1.2 christos ASSERT_OK(uv_signal_start(&signal, signum_test_cb, SIGFPE)); 66 1.1.1.2 christos ASSERT_OK(uv_signal_start(&signal, signum_test_cb, SIGSEGV)); 67 1.1.1.2 christos ASSERT_OK(uv_signal_start(&signal, signum_test_cb, SIGTERM)); 68 1.1.1.2 christos ASSERT_OK(uv_signal_start(&signal, signum_test_cb, SIGABRT)); 69 1.1.1.2 christos ASSERT_EQ(uv_signal_start(&signal, signum_test_cb, -1), UV_EINVAL); 70 1.1.1.2 christos ASSERT_EQ(uv_signal_start(&signal, signum_test_cb, NSIG), UV_EINVAL); 71 1.1.1.2 christos ASSERT_EQ(uv_signal_start(&signal, signum_test_cb, 1024), UV_EINVAL); 72 1.1.1.2 christos MAKE_VALGRIND_HAPPY(loop); 73 1.1 christos return 0; 74 1.1 christos } 75 1.1 christos #else 76 1.1 christos #include <errno.h> 77 1.1 christos #include <signal.h> 78 1.1 christos #include <stdarg.h> 79 1.1 christos #include <stdio.h> 80 1.1 christos #include <stdlib.h> 81 1.1 christos #include <string.h> 82 1.1 christos #include <unistd.h> 83 1.1 christos 84 1.1 christos #define NSIGNALS 10 85 1.1 christos 86 1.1 christos struct timer_ctx { 87 1.1 christos unsigned int ncalls; 88 1.1 christos uv_timer_t handle; 89 1.1 christos int signum; 90 1.1 christos }; 91 1.1 christos 92 1.1 christos struct signal_ctx { 93 1.1 christos enum { CLOSE, STOP, NOOP } stop_or_close; 94 1.1 christos unsigned int ncalls; 95 1.1 christos uv_signal_t handle; 96 1.1 christos int signum; 97 1.1 christos int one_shot; 98 1.1 christos }; 99 1.1 christos 100 1.1 christos 101 1.1 christos static void signal_cb(uv_signal_t* handle, int signum) { 102 1.1 christos struct signal_ctx* ctx = container_of(handle, struct signal_ctx, handle); 103 1.1.1.2 christos ASSERT_EQ(signum, ctx->signum); 104 1.1 christos if (++ctx->ncalls == NSIGNALS) { 105 1.1 christos if (ctx->stop_or_close == STOP) 106 1.1 christos uv_signal_stop(handle); 107 1.1 christos else if (ctx->stop_or_close == CLOSE) 108 1.1 christos uv_close((uv_handle_t*)handle, NULL); 109 1.1 christos else 110 1.1 christos ASSERT(0); 111 1.1 christos } 112 1.1 christos } 113 1.1 christos 114 1.1 christos static void signal_cb_one_shot(uv_signal_t* handle, int signum) { 115 1.1 christos struct signal_ctx* ctx = container_of(handle, struct signal_ctx, handle); 116 1.1.1.2 christos ASSERT_EQ(signum, ctx->signum); 117 1.1.1.2 christos ASSERT_EQ(1, ++ctx->ncalls); 118 1.1 christos if (ctx->stop_or_close == CLOSE) 119 1.1 christos uv_close((uv_handle_t*)handle, NULL); 120 1.1 christos } 121 1.1 christos 122 1.1 christos 123 1.1 christos static void timer_cb(uv_timer_t* handle) { 124 1.1 christos struct timer_ctx* ctx = container_of(handle, struct timer_ctx, handle); 125 1.1 christos 126 1.1 christos raise(ctx->signum); 127 1.1 christos 128 1.1 christos if (++ctx->ncalls == NSIGNALS) 129 1.1 christos uv_close((uv_handle_t*)handle, NULL); 130 1.1 christos } 131 1.1 christos 132 1.1 christos 133 1.1 christos static void start_watcher(uv_loop_t* loop, 134 1.1 christos int signum, 135 1.1 christos struct signal_ctx* ctx, 136 1.1 christos int one_shot) { 137 1.1 christos ctx->ncalls = 0; 138 1.1 christos ctx->signum = signum; 139 1.1 christos ctx->stop_or_close = CLOSE; 140 1.1 christos ctx->one_shot = one_shot; 141 1.1.1.2 christos ASSERT_OK(uv_signal_init(loop, &ctx->handle)); 142 1.1 christos if (one_shot) 143 1.1.1.2 christos ASSERT_OK(uv_signal_start_oneshot(&ctx->handle, signal_cb_one_shot, signum)); 144 1.1 christos else 145 1.1.1.2 christos ASSERT_OK(uv_signal_start(&ctx->handle, signal_cb, signum)); 146 1.1 christos } 147 1.1 christos 148 1.1 christos static void start_timer(uv_loop_t* loop, int signum, struct timer_ctx* ctx) { 149 1.1 christos ctx->ncalls = 0; 150 1.1 christos ctx->signum = signum; 151 1.1.1.2 christos ASSERT_OK(uv_timer_init(loop, &ctx->handle)); 152 1.1.1.2 christos ASSERT_OK(uv_timer_start(&ctx->handle, timer_cb, 5, 5)); 153 1.1 christos } 154 1.1 christos 155 1.1 christos 156 1.1 christos TEST_IMPL(we_get_signal) { 157 1.1 christos struct signal_ctx sc; 158 1.1 christos struct timer_ctx tc; 159 1.1 christos uv_loop_t* loop; 160 1.1 christos 161 1.1 christos loop = uv_default_loop(); 162 1.1 christos start_timer(loop, SIGCHLD, &tc); 163 1.1 christos start_watcher(loop, SIGCHLD, &sc, 0); 164 1.1 christos sc.stop_or_close = STOP; /* stop, don't close the signal handle */ 165 1.1.1.2 christos ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT)); 166 1.1.1.2 christos ASSERT_EQ(tc.ncalls, NSIGNALS); 167 1.1.1.2 christos ASSERT_EQ(sc.ncalls, NSIGNALS); 168 1.1 christos 169 1.1 christos start_timer(loop, SIGCHLD, &tc); 170 1.1.1.2 christos ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT)); 171 1.1.1.2 christos ASSERT_EQ(tc.ncalls, NSIGNALS); 172 1.1.1.2 christos ASSERT_EQ(sc.ncalls, NSIGNALS); 173 1.1 christos 174 1.1 christos sc.ncalls = 0; 175 1.1 christos sc.stop_or_close = CLOSE; /* now close it when it's done */ 176 1.1 christos uv_signal_start(&sc.handle, signal_cb, SIGCHLD); 177 1.1 christos 178 1.1 christos start_timer(loop, SIGCHLD, &tc); 179 1.1.1.2 christos ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT)); 180 1.1.1.2 christos ASSERT_EQ(tc.ncalls, NSIGNALS); 181 1.1.1.2 christos ASSERT_EQ(sc.ncalls, NSIGNALS); 182 1.1 christos 183 1.1.1.2 christos MAKE_VALGRIND_HAPPY(loop); 184 1.1 christos return 0; 185 1.1 christos } 186 1.1 christos 187 1.1 christos 188 1.1 christos TEST_IMPL(we_get_signals) { 189 1.1 christos struct signal_ctx sc[4]; 190 1.1 christos struct timer_ctx tc[2]; 191 1.1 christos uv_loop_t* loop; 192 1.1 christos unsigned int i; 193 1.1 christos 194 1.1 christos loop = uv_default_loop(); 195 1.1 christos start_watcher(loop, SIGUSR1, sc + 0, 0); 196 1.1 christos start_watcher(loop, SIGUSR1, sc + 1, 0); 197 1.1 christos start_watcher(loop, SIGUSR2, sc + 2, 0); 198 1.1 christos start_watcher(loop, SIGUSR2, sc + 3, 0); 199 1.1 christos start_timer(loop, SIGUSR1, tc + 0); 200 1.1 christos start_timer(loop, SIGUSR2, tc + 1); 201 1.1.1.2 christos ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT)); 202 1.1 christos 203 1.1 christos for (i = 0; i < ARRAY_SIZE(sc); i++) 204 1.1.1.2 christos ASSERT_EQ(sc[i].ncalls, NSIGNALS); 205 1.1 christos 206 1.1 christos for (i = 0; i < ARRAY_SIZE(tc); i++) 207 1.1.1.2 christos ASSERT_EQ(tc[i].ncalls, NSIGNALS); 208 1.1 christos 209 1.1.1.2 christos MAKE_VALGRIND_HAPPY(loop); 210 1.1 christos return 0; 211 1.1 christos } 212 1.1 christos 213 1.1 christos TEST_IMPL(we_get_signal_one_shot) { 214 1.1 christos struct signal_ctx sc; 215 1.1 christos struct timer_ctx tc; 216 1.1 christos uv_loop_t* loop; 217 1.1 christos 218 1.1 christos loop = uv_default_loop(); 219 1.1 christos start_timer(loop, SIGCHLD, &tc); 220 1.1 christos start_watcher(loop, SIGCHLD, &sc, 1); 221 1.1 christos sc.stop_or_close = NOOP; 222 1.1.1.2 christos ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT)); 223 1.1.1.2 christos ASSERT_EQ(tc.ncalls, NSIGNALS); 224 1.1.1.2 christos ASSERT_EQ(1, sc.ncalls); 225 1.1 christos 226 1.1 christos start_timer(loop, SIGCHLD, &tc); 227 1.1.1.2 christos ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT)); 228 1.1.1.2 christos ASSERT_EQ(1, sc.ncalls); 229 1.1 christos 230 1.1 christos sc.ncalls = 0; 231 1.1 christos sc.stop_or_close = CLOSE; /* now close it when it's done */ 232 1.1 christos uv_signal_start_oneshot(&sc.handle, signal_cb_one_shot, SIGCHLD); 233 1.1 christos start_timer(loop, SIGCHLD, &tc); 234 1.1.1.2 christos ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT)); 235 1.1.1.2 christos ASSERT_EQ(tc.ncalls, NSIGNALS); 236 1.1.1.2 christos ASSERT_EQ(1, sc.ncalls); 237 1.1 christos 238 1.1.1.2 christos MAKE_VALGRIND_HAPPY(loop); 239 1.1 christos return 0; 240 1.1 christos } 241 1.1 christos 242 1.1 christos TEST_IMPL(we_get_signals_mixed) { 243 1.1 christos struct signal_ctx sc[4]; 244 1.1 christos struct timer_ctx tc; 245 1.1 christos uv_loop_t* loop; 246 1.1 christos 247 1.1 christos loop = uv_default_loop(); 248 1.1 christos 249 1.1 christos /* 2 one-shot */ 250 1.1 christos start_timer(loop, SIGCHLD, &tc); 251 1.1 christos start_watcher(loop, SIGCHLD, sc + 0, 1); 252 1.1 christos start_watcher(loop, SIGCHLD, sc + 1, 1); 253 1.1 christos sc[0].stop_or_close = CLOSE; 254 1.1 christos sc[1].stop_or_close = CLOSE; 255 1.1.1.2 christos ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT)); 256 1.1.1.2 christos ASSERT_EQ(tc.ncalls, NSIGNALS); 257 1.1.1.2 christos ASSERT_EQ(1, sc[0].ncalls); 258 1.1.1.2 christos ASSERT_EQ(1, sc[1].ncalls); 259 1.1 christos 260 1.1 christos /* 2 one-shot, 1 normal then remove normal */ 261 1.1 christos start_timer(loop, SIGCHLD, &tc); 262 1.1 christos start_watcher(loop, SIGCHLD, sc + 0, 1); 263 1.1 christos start_watcher(loop, SIGCHLD, sc + 1, 1); 264 1.1 christos sc[0].stop_or_close = CLOSE; 265 1.1 christos sc[1].stop_or_close = CLOSE; 266 1.1 christos start_watcher(loop, SIGCHLD, sc + 2, 0); 267 1.1 christos uv_close((uv_handle_t*)&(sc[2]).handle, NULL); 268 1.1.1.2 christos ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT)); 269 1.1.1.2 christos ASSERT_EQ(tc.ncalls, NSIGNALS); 270 1.1.1.2 christos ASSERT_EQ(1, sc[0].ncalls); 271 1.1.1.2 christos ASSERT_EQ(1, sc[1].ncalls); 272 1.1.1.2 christos ASSERT_OK(sc[2].ncalls); 273 1.1 christos 274 1.1 christos /* 2 normal, 1 one-shot then remove one-shot */ 275 1.1 christos start_timer(loop, SIGCHLD, &tc); 276 1.1 christos start_watcher(loop, SIGCHLD, sc + 0, 0); 277 1.1 christos start_watcher(loop, SIGCHLD, sc + 1, 0); 278 1.1 christos sc[0].stop_or_close = CLOSE; 279 1.1 christos sc[1].stop_or_close = CLOSE; 280 1.1 christos start_watcher(loop, SIGCHLD, sc + 2, 1); 281 1.1 christos uv_close((uv_handle_t*)&(sc[2]).handle, NULL); 282 1.1.1.2 christos ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT)); 283 1.1.1.2 christos ASSERT_EQ(tc.ncalls, NSIGNALS); 284 1.1.1.2 christos ASSERT_EQ(sc[0].ncalls, NSIGNALS); 285 1.1.1.2 christos ASSERT_EQ(sc[1].ncalls, NSIGNALS); 286 1.1.1.2 christos ASSERT_OK(sc[2].ncalls); 287 1.1 christos 288 1.1 christos /* 2 normal, 2 one-shot then remove 2 normal */ 289 1.1 christos start_timer(loop, SIGCHLD, &tc); 290 1.1 christos start_watcher(loop, SIGCHLD, sc + 0, 0); 291 1.1 christos start_watcher(loop, SIGCHLD, sc + 1, 0); 292 1.1 christos start_watcher(loop, SIGCHLD, sc + 2, 1); 293 1.1 christos start_watcher(loop, SIGCHLD, sc + 3, 1); 294 1.1 christos sc[2].stop_or_close = CLOSE; 295 1.1 christos sc[3].stop_or_close = CLOSE; 296 1.1 christos uv_close((uv_handle_t*)&(sc[0]).handle, NULL); 297 1.1 christos uv_close((uv_handle_t*)&(sc[1]).handle, NULL); 298 1.1.1.2 christos ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT)); 299 1.1.1.2 christos ASSERT_EQ(tc.ncalls, NSIGNALS); 300 1.1.1.2 christos ASSERT_OK(sc[0].ncalls); 301 1.1.1.2 christos ASSERT_OK(sc[1].ncalls); 302 1.1.1.2 christos ASSERT_EQ(1, sc[2].ncalls); 303 1.1.1.2 christos ASSERT_EQ(1, sc[2].ncalls); 304 1.1 christos 305 1.1 christos /* 1 normal, 1 one-shot, 2 normal then remove 1st normal, 2nd normal */ 306 1.1 christos start_timer(loop, SIGCHLD, &tc); 307 1.1 christos start_watcher(loop, SIGCHLD, sc + 0, 0); 308 1.1 christos start_watcher(loop, SIGCHLD, sc + 1, 1); 309 1.1 christos start_watcher(loop, SIGCHLD, sc + 2, 0); 310 1.1 christos start_watcher(loop, SIGCHLD, sc + 3, 0); 311 1.1 christos sc[3].stop_or_close = CLOSE; 312 1.1 christos uv_close((uv_handle_t*)&(sc[0]).handle, NULL); 313 1.1 christos uv_close((uv_handle_t*)&(sc[2]).handle, NULL); 314 1.1.1.2 christos ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT)); 315 1.1.1.2 christos ASSERT_EQ(tc.ncalls, NSIGNALS); 316 1.1.1.2 christos ASSERT_OK(sc[0].ncalls); 317 1.1.1.2 christos ASSERT_EQ(1, sc[1].ncalls); 318 1.1.1.2 christos ASSERT_OK(sc[2].ncalls); 319 1.1.1.2 christos ASSERT_EQ(sc[3].ncalls, NSIGNALS); 320 1.1 christos 321 1.1.1.2 christos MAKE_VALGRIND_HAPPY(loop); 322 1.1 christos return 0; 323 1.1 christos } 324 1.1 christos 325 1.1 christos #endif /* _WIN32 */ 326