| //===-- Unittests for ucontext routines -----------------------------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "src/ucontext/getcontext.h" | |
| #include "src/ucontext/setcontext.h" | |
| #include "src/signal/sigaddset.h" | |
| #include "src/signal/sigemptyset.h" | |
| #include "src/signal/sigprocmask.h" | |
| #include "test/UnitTest/Test.h" | |
| #include "include/llvm-libc-macros/signal-macros.h" | |
| namespace LIBC_NAMESPACE { | |
| static bool is_signal_set(const sigset_t *set, int signum) { | |
| // TODO: Replace this with sigismember once it is implemented. | |
| // NSIG is 64, sigset_t is an array of unsigned long. | |
| // Signum is 1-indexed. | |
| int word = (signum - 1) / (sizeof(unsigned long) * 8); | |
| int bit = (signum - 1) % (sizeof(unsigned long) * 8); | |
| return (set->__signals[word] & (1UL << bit)) != 0; | |
| } | |
| TEST(LlvmLibcUcontextTest, BasicStubTest) { | |
| static volatile int jumped = 0; | |
| ucontext_t ctx; | |
| ASSERT_EQ(getcontext(&ctx), 0); | |
| if (!jumped) { | |
| jumped = 1; | |
| setcontext(&ctx); | |
| ASSERT_TRUE(false && "setcontext should not return on success"); | |
| } | |
| } | |
| TEST(LlvmLibcUcontextTest, SignalMaskTest) { | |
| sigset_t set, old_set; | |
| sigemptyset(&set); | |
| sigaddset(&set, SIGUSR1); | |
| // Set mask to [SIGUSR1] using sigprocmask | |
| sigprocmask(SIG_SETMASK, &set, &old_set); | |
| ucontext_t ctx; | |
| getcontext(&ctx); | |
| // Verify that getcontext captured the mask | |
| ASSERT_TRUE(is_signal_set(&ctx.uc_sigmask, SIGUSR1)); | |
| ASSERT_FALSE(is_signal_set(&ctx.uc_sigmask, SIGUSR2)); | |
| sigset_t new_set; | |
| static volatile int mask_jumped = 0; | |
| if (mask_jumped == 0) { | |
| mask_jumped = 1; | |
| sigemptyset(&new_set); | |
| sigaddset(&new_set, SIGUSR2); | |
| sigprocmask(SIG_SETMASK, &new_set, nullptr); | |
| setcontext(&ctx); | |
| } | |
| // Check current mask | |
| sigset_t current; | |
| sigprocmask(SIG_BLOCK, nullptr, ¤t); | |
| // Restore original mask for clean state | |
| sigprocmask(SIG_SETMASK, &old_set, nullptr); | |
| ASSERT_TRUE(is_signal_set(¤t, SIGUSR1)); | |
| ASSERT_FALSE(is_signal_set(¤t, SIGUSR2)); | |
| } | |
| } // namespace LIBC_NAMESPACE |