Skip to content

LOG_EVERY_N seems not thread safe in C++11 and newer #804

Open
@Nimrod0901

Description

@Nimrod0901

Consider the code

  static std::atomic<int> LOG_OCCURRENCES(0), LOG_OCCURRENCES_MOD_N(0); \
  ++LOG_OCCURRENCES; \
  if (++LOG_OCCURRENCES_MOD_N > n) LOG_OCCURRENCES_MOD_N -= n; \
  if (LOG_OCCURRENCES_MOD_N == 1) 

Although every statement here is an atomic operation, other threads may fall into the first if condition even though LOG_OCCURRENCES_MOD_N already subtracts n
Simple test

#include <glog/logging.h>
#include <thread>
#include <atomic>

void bar() {
    static std::atomic<int> n(0);
    LOG_EVERY_N(INFO, 2) << ++n;
}
int main() {
    std::vector<std::thread> threads;
    for (size_t i = 0; i < 4000; ++i) {
        std::thread t(&bar);
        threads.emplace_back(std::move(t));
    }
    for (auto& thread : threads) {
        thread.join();
    }
}

Sometimes the output will not be equal to 2000.

I have no idea if it is thread-safe in the older compilers.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions