‹ BackHN Continuity

Thread

C++26: Trivial infinite loops are no longer undefined behaviour

173 points · 290 comments · ibobev

  1. JoshTriplett · · focus · HN ↗
    > When both conditions are met, the loop body is replaced with a call to std::this_thread::yield().

    Insert screaming here.

    An infinite loop, with no library calls whatsoever, gets a system call inserted. That's a horrible surprise waiting to happen.

    The entire concept of the "forward progress guarantee" is broken. An infinite loop should compile to an infinite loop. Nothing more, nothing less.

    1. ameliaquining · · focus · HN ↗
      I'm curious, what exactly do you imagine going wrong here?
      1. rcxdude · · focus · HN ↗
        The biggest headache will probably be it getting emitted in inappropriate contexts: where there is no actual means to sched_yield for whatever reason (bare metal, kernel, whatever). The second is just that the behaviour of the infinite loop changes: suddenly you're getting a bunch of extra system calls from your spinning thread instead of just a high CPU usage, which could disguise the issue or perhaps cause problems for other parts of the system. I don't see a good reason for the transformation: pretty much any time you are writing a bare infinite loop like this you don't want anything else to happen (it's also silly that it only happens with a particular spelling of an infinite loop, keeping the others still undefined).
        1. nicebyte · · focus · HN ↗
          arguably there are already several places in the language where things like this can happen. for example, initializing a static function variable has certain thread safety guarantees (two threads entering the function won't step on each other), and while it's nice to not worry about it, this can certainly be a problem if you're trying to stay close to the metal and not pull in any dependencies.

          > I don't see a good reason for the transformation: pretty much any time you are writing a bare infinite loop like this you don't want anything else to happen (it's also silly that it only happens with a particular spelling of an infinite loop, keeping the others still undefined).

          I'm not disagreeing with you, but two things worth considering are 1) you don't always write loops like that _intentionally_; 2) if a bug like that slips into production system, it would be good to make sure it doesn't starve other threads.

          1. rcxdude · · focus · HN ↗
            This is true. Static initialization will often generate calls to lock functions and that can be a faff to deal with. But I don't see what the point of the sched_yield() is. Using it at all is already a code smell and calling it repeatedly in a tight loop is the kind of thing kernel developers were trying to beat out of application developers decades ago because it just isn't really very helpful (and often actively harmful) with any but the dumbest of schedulers. It's certainly not very useful for avoiding thread starvation.
Open on Hacker News to reply ↗

Unofficial Hacker News client; not affiliated with Y Combinator.