<commit_before>#include "arch/runtime/event_queue/poll.hpp"

#include <unistd.h>
#include <sched.h>
#include <stdio.h>
#include <errno.h>
#include <poll.h>
#include <string.h>

#include <new>
#include <algorithm>
#include <string>


#include "config/args.hpp"
#include "utils.hpp"
#include "arch/runtime/event_queue.hpp"
#include "arch/runtime/thread_pool.hpp"
#include "perfmon/perfmon.hpp"

int user_to_poll(int mode) {

    rassert((mode & (poll_event_in | poll_event_out)) == mode);

    int out_mode = 0;
    if (mode & poll_event_in) out_mode |= POLLIN;
    if (mode & poll_event_out) out_mode |= POLLOUT;

    return out_mode;
}

int poll_to_user(int mode) {

    rassert((mode & (POLLIN | POLLOUT | POLLERR | POLLHUP | POLLRDHUP)) == mode);

    int out_mode = 0;
    if (mode & POLLIN) out_mode |= poll_event_in;
    if (mode & POLLOUT) out_mode |= poll_event_out;
    if (mode & POLLERR) out_mode |= poll_event_err;
    if (mode & POLLHUP) out_mode |= poll_event_hup;
    if (mode & POLLRDHUP) out_mode |= poll_event_rdhup;

    return out_mode;
}

poll_event_queue_t::poll_event_queue_t(linux_queue_parent_t *_parent)
    : parent(_parent) {
}

void poll_event_queue_t::run() {
    int res;

#ifdef LEGACY_LINUX
    // Create an empty sigmask for ppoll
    sigset_t sigmask, sigmask_full;
    res = sigemptyset(&sigmask);
    guarantee_err(res == 0, "Could not create an empty signal mask");

    res = sigfillset(&sigmask_full);
    guarantee_err(res == 0, "Could not create a full signal mask");
#endif

    // Now, start the loop
    while (!parent->should_shut_down()) {
        // Grab the events from the kernel!
#ifdef LEGACY_LINUX
        res = ppoll(&watched_fds[0], watched_fds.size(), NULL, &sigmask);
#else
        res = poll(&watched_fds[0], watched_fds.size(), 0);
#endif

        // ppoll might return with EINTR in some cases (in particular
        // under GDB), we just need to retry.
        if (res == -1 && errno == EINTR) {
            res = 0;
        }

        // The only likely poll error here is ENOMEM, which we
        // have no way of handling, and it's probably fatal.
        guarantee_err(res != -1, "Waiting for poll events failed");

        block_pm_duration event_loop_timer(&pm_eventloop);

        int count = 0;
        for (unsigned int i = 0; i < watched_fds.size(); i++) {
            if(watched_fds[i].revents != 0) {
                linux_event_callback_t *cb = callbacks[watched_fds[i].fd];
                cb->on_event(poll_to_user(watched_fds[i].revents));
                count++;
            }
            if(count == res)
                break;
        }

#ifdef LEGACY_LINUX
        // If ppoll is busy with file descriptors, the piece of shit
        // kernel starves out signals, so we need to unblock them to
        // let the signal handlers get called, and then block them
        // right back. What a sensible fucking system.
        res = pthread_sigmask(SIG_SETMASK, &sigmask, NULL);
        guarantee_err(res == 0, "Could not unblock signals");
        res = pthread_sigmask(SIG_SETMASK, &sigmask_full, NULL);
        guarantee_err(res == 0, "Could not block signals");
#endif

        parent->pump();
    }

#ifdef LEGACY_LINUX
    // Unblock all signals
    res = pthread_sigmask(SIG_SETMASK, &sigmask, NULL);
    guarantee_err(res == 0, "Could not unblock signals");
#endif
}<commit_msg>Modified the LEGACY_LINUX part of poll.cc because shutting down RethinkDB versions with LEGACY_LINUX on was causing an error (interrupt handler called on wrong thread). See comment for details.<commit_after>#include "arch/runtime/event_queue/poll.hpp"

#include <unistd.h>
#include <sched.h>
#include <stdio.h>
#include <errno.h>
#include <poll.h>
#include <string.h>

#include <new>
#include <algorithm>
#include <string>


#include "config/args.hpp"
#include "utils.hpp"
#include "arch/runtime/event_queue.hpp"
#include "arch/runtime/thread_pool.hpp"
#include "perfmon/perfmon.hpp"

int user_to_poll(int mode) {

    rassert((mode & (poll_event_in | poll_event_out)) == mode);

    int out_mode = 0;
    if (mode & poll_event_in) out_mode |= POLLIN;
    if (mode & poll_event_out) out_mode |= POLLOUT;

    return out_mode;
}

int poll_to_user(int mode) {

    rassert((mode & (POLLIN | POLLOUT | POLLERR | POLLHUP | POLLRDHUP)) == mode);

    int out_mode = 0;
    if (mode & POLLIN) out_mode |= poll_event_in;
    if (mode & POLLOUT) out_mode |= poll_event_out;
    if (mode & POLLERR) out_mode |= poll_event_err;
    if (mode & POLLHUP) out_mode |= poll_event_hup;
    if (mode & POLLRDHUP) out_mode |= poll_event_rdhup;

    return out_mode;
}

poll_event_queue_t::poll_event_queue_t(linux_queue_parent_t *_parent)
    : parent(_parent) {
}

void poll_event_queue_t::run() {
    int res;

#ifdef LEGACY_LINUX
    // Create an restricted sigmask for ppoll
    // In the upcoming loop, we want to continue blocking signals
    // (especially SIGINT and SIGTERM, which the main thread
    // has interrupt handlers for). However, LEGACY_LINUX
    // builds use timerfd_provider, which requires
    // this thread to be able to catch the TIMER_NOTIFY_SIGNAL.
    // sigmask_restricted is configured to allow this
    // one signal through while blocking the other signals
    // for the main thread to handle.
    sigset_t sigmask_restricted, sigmask_full;
    res = sigfillset(&sigmask_restricted);
    guarantee_err(res == 0, "Could not create an full signal mask");
    res = sigdelset(&sigmask_restricted, TIMER_NOTIFY_SIGNAL);
    guarantee_err(res == 0, "Could not remove TIMER_NOTIFY_SIGNAL from signal mask");

    res = sigfillset(&sigmask_full);
    guarantee_err(res == 0, "Could not create a full signal mask");
#endif

    // Now, start the loop
    while (!parent->should_shut_down()) {
        // Grab the events from the kernel!
#ifdef LEGACY_LINUX
        res = ppoll(&watched_fds[0], watched_fds.size(), NULL, &sigmask_restricted);
#else
        res = poll(&watched_fds[0], watched_fds.size(), 0);
#endif

        // ppoll might return with EINTR in some cases (in particular
        // under GDB), we just need to retry.
        if (res == -1 && errno == EINTR) {
            res = 0;
        }

        // The only likely poll error here is ENOMEM, which we
        // have no way of handling, and it's probably fatal.
        guarantee_err(res != -1, "Waiting for poll events failed");

        block_pm_duration event_loop_timer(&pm_eventloop);

        int count = 0;
        for (unsigned int i = 0; i < watched_fds.size(); i++) {
            if(watched_fds[i].revents != 0) {
                linux_event_callback_t *cb = callbacks[watched_fds[i].fd];
                cb->on_event(poll_to_user(watched_fds[i].revents));
                count++;
            }
            if(count == res)
                break;
        }

#ifdef LEGACY_LINUX
        // If ppoll is busy with file descriptors, the piece of shit
        // kernel starves out signals, so we need to unblock them to
        // let the signal handlers get called, and then block them
        // right back. What a sensible fucking system.
        res = pthread_sigmask(SIG_SETMASK, &sigmask_restricted, NULL);
        guarantee_err(res == 0, "Could not unblock signals");
        res = pthread_sigmask(SIG_SETMASK, &sigmask_full, NULL);
        guarantee_err(res == 0, "Could not block signals");
#endif

        parent->pump();
    }

#ifdef LEGACY_LINUX
    // Unblock all signals
    res = pthread_sigmask(SIG_SETMASK, &sigmask_restricted, NULL);
    guarantee_err(res == 0, "Could not unblock signals");
#endif
}
{'fraction_non_alphanumeric': 0.11251980982567353, 'fraction_numerical': 0.004358161648177496, 'mean_word_length': 2.948383733055266, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7642728', 'n_tokens_mistral': 2601, 'n_tokens_neox': 2495, 'n_words': 717}