topic_monitor_t::topic_monitor_t() {
    // Set up our pipes. Assert it succeeds.
    auto pipes = make_autoclose_pipes({});
    assert(pipes.has_value() && "Failed to make pubsub pipes");
    pipes_ = pipes.acquire();

    // Make sure that our write side doesn't block, else we risk hanging in a signal handler.
    // The read end must block to avoid spinning in await.
    DIE_ON_FAILURE(make_fd_nonblocking(pipes_.write.fd()));

#if TOPIC_MONITOR_TSAN_WORKAROUND
    DIE_ON_FAILURE(make_fd_nonblocking(pipes_.read.fd()));
#endif
}
Exemple #2
0
void io_buffer_t::complete_background_fillthread() {
    ASSERT_IS_MAIN_THREAD();
    assert(fillthread_ && "Should have a fillthread");
    shutdown_fillthread_.store(true, std::memory_order_relaxed);
    void *ignored = nullptr;
    int err = pthread_join(*fillthread_, &ignored);
    DIE_ON_FAILURE(err);
    fillthread_.reset();
}
Exemple #3
0
/// Spawn another thread. No lock is held when this is called.
static void iothread_spawn() {
    // The spawned thread inherits our signal mask. We don't want the thread to ever receive signals
    // on the spawned thread, so temporarily block all signals, spawn the thread, and then restore
    // it.
    sigset_t new_set, saved_set;
    sigfillset(&new_set);
    DIE_ON_FAILURE(pthread_sigmask(SIG_BLOCK, &new_set, &saved_set));

    // Spawn a thread. If this fails, it means there's already a bunch of threads; it is very
    // unlikely that they are all on the verge of exiting, so one is likely to be ready to handle
    // extant requests. So we can ignore failure with some confidence.
    pthread_t thread = 0;
    pthread_create(&thread, NULL, iothread_worker, NULL);

    // We will never join this thread.
    DIE_ON_FAILURE(pthread_detach(thread));
    debug(5, "pthread %p spawned", (void *)(intptr_t)thread);
    // Restore our sigmask.
    DIE_ON_FAILURE(pthread_sigmask(SIG_SETMASK, &saved_set, NULL));
}