https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98376

            Bug ID: 98376
           Summary: this_thread::sleep_for(short duration) can sleep
                    forever on Linux
           Product: gcc
           Version: 11.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: paul.groke at dynatrace dot com
  Target Milestone: ---

If libstdc++ is configured with _GLIBCXX_USE_NANOSLEEP (which seems to be the
case on most systems), it will use nanosleep in this_thread::sleep_for like
this:

        __gthread_time_t __ts =
          {
            static_cast<std::time_t>(__s.count()),
            static_cast<long>(__ns.count())
          };
        while (::nanosleep(&__ts, &__ts) == -1 && errno == EINTR)
          { }

However on Linux, such a nanosleep loop can run forever because of a Linux bug
that's documented here:
https://man7.org/linux/man-pages/man2/nanosleep.2.html#BUGS

For this to happen the thread needs to receive signals at a high frequency
which seems to be rather uncommon.

However there's a Go feature called non-cooperative preemption that can trigger
this quite easily, see
https://github.com/golang/proposal/blob/master/design/24543-non-cooperative-preemption.md
https://github.com/golang/go/blob/master/src/runtime/signal_unix.go#L352
https://github.com/golang/go/blob/master/src/runtime/preempt.go#L223

This could lead to problems when on Linux, native code that uses libstdc++ is
called from a Go thread. The Go thread executing this_thread::sleep_for will
loop forever calling nanosleep and the other Go thread that tries to preempt it
will also loop forever, perpetually trying to preempt it.

Reply via email to