error()/error_at_line() and threads

enh enh@google.com
Thu Jun 11 16:52:04 GMT 2026


On Thu, Jun 11, 2026 at 12:44 PM Florian Weimer <fweimer@redhat.com> wrote:
>
> > the man page further has the rather over-optimistic:
> >
> >        The internal error_one_per_line variable is accessed (without any
> >        form of synchronization, but since it's an int used once, it
> >        should be safe enough), and if error_one_per_line is set nonzero,
> >        the internal static variables (not exposed to users) used to hold
> >        the last printed filename and line number are accessed and
> >        modified without synchronization; the update is not atomic and it
> >        occurs before disabling cancelation, so it can be interrupted only
> >        after one of the two variables is modified.  After that,
> >        error_at_line() is very much like error().
> >
> > but neither say anything about error_message_count. a quick test
> > program shows that, as you'd expect, some increments get lost in the
> > presence of many threads.
>
> With glibc?  That's surprising because we lock stderr before updating
> error_message_count.

yeah, i reproduced this on debian glibc 2.42. the following program
often comes up one short...

#include <error.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <thread>
#include <vector>

int main() {
  int old_stderr = dup(STDERR_FILENO);
  int dev_null = open("/dev/null", O_WRONLY);
  dup2(dev_null, STDERR_FILENO);
  close(dev_null);

  error_message_count = 0;

  const int kNumThreads = 50;
  const int kIterations = 10000;
  std::vector<std::thread> threads;
  for (int i = 0; i < kNumThreads; ++i) {
    threads.emplace_back([]() {
      for (int j = 0; j < kIterations; ++j) {
        error(0, 0, "test %d", j);
      }
    });
  }
  for (auto& t : threads) {
    t.join();
  }

  dup2(old_stderr, STDERR_FILENO);
  close(old_stderr);

  printf("%d\n", kNumThreads * kIterations);
  printf("%u\n", error_message_count);
  return 0;
}

> Thanks,
> Florian
>


More information about the Libc-alpha mailing list